Let's say that we want to declare three integers, p, q, and r. Best practice is to initialize them to 0. The C way of doing this is:
int p, q, r;
p = q = r = 0;
The C++ way of doing this is
int p(0), q(0), r(0);
In C, things are nice and tight; 0 is only used once. In contrast, the C++ call requires 0 to be repeated three times--once for each variable. A bit verbose.
Is there a more concise way of initializing variables using the C++ method, or is the initial value required for each variable declaration?
Also, any problem mixing the C-style initialization with C++ code? Thx :^)
EDIT: Fixed code to compile properly. Now, it takes two lines to declare and initialize the variables, so the question isn't very good, but I will leave it here for posterity. Hopefully helps someone.
Best practice is to initialize them to 0.
This may be even harmful, as it would silence the compiler's protection. Consider following code:
int p, q, r;
p = q = r = 0;
// ...
p = FIRST_INDEX;
r = LAST_INDEX; // ups, we forget to initialize q with some real value
// ...
doSomething(p, q, r);
Normally, you will get a warning like:
warning: 'q' is used uninitialized in this function [-Wuninitialized]
but since the q is already intialized, the compiler thinks that is fine.
Intermixing declarations with code
If you have C++ or at least C99-conformant compiler, then one may argue, that code could be designed better, by moving variables' declarations closest to their first usage:
// some executable code
int p = FIRST_INDEX;
int q = LAST_INDEX;
int r = getSampleCoefficient();
doSomething(p, q, r);
This way, the issue presented in previous example may be avoided completely, since there is no gap between declarations and actual code.
You may use p = q = r = 0; in C++, it's just matter of coding style.
Related
I heard that small objects are passed in CPU registers on function calls. I tried to search the maximum of when this is not anymore the case. I know that string_view is passed in registers. But what is the limit? I know this is architecture dependent, but it seems that even really large objects can be passed by registers. Compare the following:
(Check it out on Quickbench)
struct big_object
{
int a_;
double b_;
char c_;
long long d_;
bool e_;
int f_;
double g_;
char h_;
long long i_;
bool j_;
int k_;
double l_;
char m_;
long long n_;
bool o_;
};
big_object obj = {
.a_ = 2,
.b_ = 2.5,
.c_ = 'A',
.d_ = 1203912045891732283,
.e_ = false,
.f_ = 10,
.g_ = 15.5,
.h_ = 'D',
.i_ = 123123123,
.j_ = true,
.k_ = 10,
.l_ = 15.5,
.m_ = 'D',
.n_ = 123123123,
.o_ = true,
};
volatile int a;
volatile double b;
volatile char c;
volatile long long d;
volatile bool e;
volatile int f;
volatile double g;
volatile char h;
volatile long long i;
volatile bool j;
volatile int k;
volatile double l;
volatile char m;
volatile long long n;
volatile bool o;
int foo(big_object obj)
{
a = obj.a_;
b = obj.b_;
c = obj.c_;
d = obj.d_;
e = obj.e_;
f = obj.f_;
g = obj.g_;
h = obj.h_;
i = obj.i_;
j = obj.j_;
k = obj.k_;
l = obj.l_;
m = obj.m_;
n = obj.n_;
o = obj.o_;
return 1;
}
int foo_ref(big_object& obj)
{
a = obj.a_;
b = obj.b_;
c = obj.c_;
d = obj.d_;
e = obj.e_;
f = obj.f_;
g = obj.g_;
h = obj.h_;
i = obj.i_;
j = obj.j_;
k = obj.k_;
l = obj.l_;
m = obj.m_;
n = obj.n_;
o = obj.o_;
return 1;
}
static void Foo(benchmark::State& state) {
// Code inside this loop is measured repeatedly
for (auto _ : state) {
foo(obj);
}
}
// Register the function as a benchmark
BENCHMARK(Foo);
static void FooRef(benchmark::State& state) {
// Code before the loop is not measured
for (auto _ : state) {
foo_ref(obj);
}
}
BENCHMARK(FooRef);
This compiles to exactly the same code and hence provide the same performance. I'm not an assembly pro, but I think I can see that a lot of registers are used to pass the object to the function. I know that there are even more physical CPU registers than logical ones, but does this mean that in any practical case, passing by reference is actually superfluous?
When function call is optimized out, when function is inlined, when you use pointers instead of objects and compiler decides that it's not worth copying, to name a few. There's no clear ruleset that compiler programmers have to follow other than C++ standard.
but does this mean that in any practical case, passing by reference is actually superfluous?
No it isn't, references are a semantic construct and not an optimization "trick", so treat them as such.
References are simply aliases to variables. Everything else is quite literally up to the compiler. One useful properly of mutable reference is that mutated object actually changes on the caller side too once the function returns.
Sure, you can also use a pointer to achieve same thing, but an even more useful property of reference is a guarantee that the object you will be accessing is valid, while a pointer is nullable.
Speaking of which, even pointers are treated more or less the same nowadays, just look at -findirect-inlining in GCC, in similar way, float* can be optimized out by a compiler to simply a direct float copy. I can't remember the name of this optimization, but I know for a fact that GCC at least used to have it. And if you have a function like float add(float* a, float* b), it will be inlined in most cases so it doesn't matter how you write it. It's simply a matter of choosing the most clear version.
Instead of worrying about things you don't understand, nor even need to, you should focus on semantics of your code. Let's be real, you're using a high level language like C++ instead of hand optimizing all ISA yourself is precisely because you want someone else to do hard work for you, so how come you don't trust them when that's the sole job they were given?
For example, it's pointless to take const& as parameter just to copy the object. If you want a copy of object in your function, then write so. Not only is this cleaner and more obvious to programmers that you will be copying, but it's clearer even to the compiler, which is also made by programmers. The fact that you benefit from certain optimizations is the only thing that's superfluous here. You're simply making it clear to anyone reading declaration that this object right there will be copied, that's all that matters. It doesn't matter how slow it is, you need to copy, so you copy.
Write code that's readable and understandable, you can worry about performance when you have a working program. If you can think of something "ingenious", the matter of fact is that compiler programmers thought of it before already.
And by the way, your benchmark doesn't benchmark anything. You're literally comparing identical code.
So like I already wrote before, do you want to copy the struct? Or simply reference something in it? That's the only thing that matters.
I'm reading a piece of code which does this
void *ptr_to_something = (void*)0x23; // I made this up, it's just a pointer to something
void *addr;
void *dst = (void*)(addr = ptr_to_something); // This is the line that confuses me
it seems to assign a pointer to something to another pointer of the same thing. And that's okay.. but then the result is enclosed in parenthesis, cast to the same thing and somehow reassigned to a third pointer to the same thing.
Is this valid C++ at all? Is it guaranteed that assigning the result of an assignment yields the same assigned object?
It is valid in C++ to do:
int a, b, c;
a = b = c = 1;
So, therefore the result of an assignment is the value of that assignment.
What the cast is for, is a mystery*. Have you tried removing it, and does that generate a warning?
*not a mystery, just perhaps unnecessary.
This is valid C++. The choice to format the code this way is odd and not advised, but it's perfectly legal.
This code is equivalent to this (what I consider to be better written) code:
void *ptr_to_something = (void*)0x23;
void *addr = ptr_to_something;
void *dst = addr;
I'm trying to use the GNU Scientific Library and am having trouble understanding its documentation. Here's the sample program from the page on gsl_rng_env_setup:
#include <stdio.h>
#include <gsl/gsl_rng.h>
gsl_rng * r; /* global generator */
int
main (void)
{
const gsl_rng_type * T;
gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc (T);
printf ("generator type: %s\n", gsl_rng_name (r));
printf ("seed = %lu\n", gsl_rng_default_seed);
printf ("first value = %lu\n", gsl_rng_get (r));
gsl_rng_free (r);
return 0;
}
My problems start with the third line, gsl_rng * r. This is clearly not multiplication (neither variable defined yet), so it must be pointer notation. However from the C++ tutorial on pointers, I would expect something like gsl_rng = *r, which would take the value of r and store that as gsl_rng. My guess is that gsl_rng isn't a variable, but some GNU Scientific library command; however I don't understand the documentation page for it also: this command is clearly not of the form gsl_rng * gsl_rng_alloc (const gsl_rng_type * T) - even if r = gsl_rng_alloc, this command doesn't have brackets.
It doesn't help that a bit further down we have the line const gsl_rng_type * T which is of the same form but also clearly does something different. This line seems to be defining gsl_rng_type as a constant, and assigning it the value of *T - but this is missing an assignment operator. Yet T must be a variable, since a few lines later it's assigned the value of gsl_rng_default ...
My problems seem to be extremely basic which is troubling. Can anyone point me in the right direction?
gsl_rng is a type. The statement gsl_rng * r; declares a global variable named r with type pointer to gsl_rng.
Later, there is this line r = gsl_rng_alloc (T);, which assigns some value to that declared variable.
This is basic C++, so maybe you should start with some good book, if you want to understand such code.
The trick is to remember that there are different kinds of random number generators. Each one is its' own class. The gsl_rng_alloc method will create a random number generator object for you but wants to know what class to use. You tell it what class to use by passing the class. Then the method uses that class to instantiate an object for you. It returns to you a pointer to the object that it created for you.
I know that the following, if possible, would be an absolutely bad practice, but I want to know if this is possible.
The question is the following: is it possible in C++ (and in a way the compiler does not throw any warning), to perform a useless arithmetic operation with a function returning a void.
std::vector<int> v;
int i = 42 + v.resize(42);
/* How to transform the last line to execute resize and to have i = 42 */
I know that this is stupid, but that is not the question...
I'm not sure it makes much sense, but you could use the comma operator here:
int i = (v.resize(42), 42);
You could use the comma operator:
int i = (v.resize(42), 42);
and with GCC you could use its statement expression extension:
int i = ({v.resize(42); 42;})
and in standard C++11 you could use and call an anonymous closure:
int i = ([&v]() {v.resize(42); return 42;}());
Type void has no values so it may not be used in arithmetic expressions.
In my opinion the design of member function resize is bad. Instead of voidit should return the object itself. In this case you could write for example
int i = v.resize(42).size();
I pointed out about this in the forum where the C++ Standard is discussed.
As for your question then you can write
int i = ( v.resize(42), v.size() );
using the comma operator.
Or maybe it would be better to separate these two calls
v.resize(42);
int i = v.size();
Don't see the point, but here's another way
std::tie(i, std::ignore) = std::make_tuple(42, (v.resize(42),1) );
Also you can do:
if ((i=42)) v.resize(42);
And don't forget
do { v.resize(42); } while (!(i=42));
And the favorite
(i=42) ? v.resize(42) : i;
Or (the only serious c++ in the post)
int i(0);
std::vector<int> v(i=42);
Come on, this has no end
.....
I'm used to program in C# or Java, so I'm doing really bad in C++. I believe it's easy but I just can't make this work. Please help me.
I have this:
void swap(vector * vet, int i, int j)
{
int temp = vet[i];
vet[i] = vet[j];
vet[j] = temp;
}
I'm calling the method this way:
swap(&vet, j, j - 1);
What I want is to pass the vector using pointers instead of using value.
Obs: The code compiles well without the "*" and "&".
Please don't say that I have to at least try to study pointers, because I did. I just can't make this damn thing work!
You should take the vector by reference rather than "pass by pointer".
void swap(std::vector<int>& vet, std::size_t i, std::size_t j)
{
using std::swap;
swap(vet[i], vet[j]);
}
http://en.cppreference.com/w/cpp/algorithm/swap
Note the more idiomatic:
http://en.cppreference.com/w/cpp/algorithm/iter_swap
Everyone has thus far responded by telling you to use references, which is correct, but they fail to explain why your code doesn't work. The problem here is that you do not understand pointer arithmetic.
Let's say we have a a pointer to 10 ints:
// best to use a vector for this, but for the sake of example...
int *p = new int[10];
Now, if we want to change the value of the second int in that chunk of memory we can write:
*(p + 1) = 20;
Or, the equivalent:
p[1] = 20;
See? Those two lines do the same thing. Adding n to a pointer increases the address of the pointer by n * sizeof *p bytes. Pointer arithmetic is convenient because it hides the sizeof bit from you and allows you to work with logical units (elements) instead of bytes.
So, knowing that, back to your broken code:
vet[i] = vet[j];
This indexes i * sizeof *vet bytes away from the pointer, i.e., i full vectors away from the base address. Obviously that is wrong, you wanted to invoke operator[] on the vector, i.e., treat it as an array. It is not an array however, so the correct syntax would be:
(*vec)[i]
Or
vec->operator[](i);
That said... just use a reference. Safer (object guaranteed to be valid) and idiomatic.
You can try something like....
void swap(vector<int> &vet, int i, int j)
{
int temp = vet[i];
vet[i] = vet[j];
vet[j] = temp;
}
and call your swap function as
swap(vet,i,j);
Bottomline: Use reference variables.They are more like reference in Java.
In fact, in C++ you'd just say
using std::swap;
swap(vet[i], vet[j]);