In some C++ sources I saw that an expression result can be saved as a constant reverence. Like this:
const int &x = y + 1;
What does it mean?
Is there any documentation on this? I can't find it..
For me it seems to be equivalent to:
const int x = y + 1;
since result of the program stays the same. Is it truly equivalent?
If yes why does the language allows the first way to write it at all? It looks confusing.
If no what is the difference?
The difference should be whether or not the result is copied/moved. In the first case:
const int& x = y + 1;
The value of y+1 is essentially saved as a temporary value. We then initialize a reference x to this temporary result. In the other case:
const int x = y + 1;
We compute y + 1 and initialize a constant variable x with the value.
In practice with integers there will be no visible difference. If y+1 happened to be a large data structure, e.g., a class which is 1MB of data, this could make a significant difference.
Related
int f(int &x, int c)
{
c = c - 1;
if (c == 0) return 1;
x = x + 1;
return f(x, c) * x;
}
int x = 5;
cout << f(x,5);
In the example above the four possible answers to choose from are:
3024
6561
55440
161051
Function f(int &x, int c) is called four times after the first call before it reaches the base case where it returns the result which is 6561. My guess was 3024 but I was wrong. Even if the x variable which is passed by reference increments in each call of f(int &x, int c) and takes the values 6->7->8->9 respectively the final result of this recursion is equal to 9^4.
So my question is: Variable x is passed by reference and is equal to 9 when it reaches the base case. Does that mean that all the stages of recursion will have this value for variable x even if they had a different value when they've been called?
No, there are more than four answers to choose from.
The fetch of x for the recursive function call, and the fetch of x for the right hand side of multiplication, is not sequenced with each other; and as such the evaluation order is unspecified.
This doesn't mean that the evaluation order would be some particular evaluation order, and it's only necessary to figure it out. This means that the final results can:
Vary depending on the compiler.
Vary each time this program executes.
The evaluation order may also be different for each individual recursive call. Each recursive call can end up using a different evaluation order, too. "Unspecified" means "unspecified". Any possibility can happen. Each individual time.
I didn't bother to calculate all actual possibilities here. It's better to invest one's own time on something that should work properly, instead of on something that obviously can never work properly.
If you want a specific evaluation order, it's going to be either this:
int y=x;
return f(x, c) * y;
Or this:
int y=f(x, c);
return y * x;
This evaluation order is now specified.
Consider the following snippets:
C++:
#include <iostream>
using namespace std;
int main()
{
int x = 10, y = 20;
y = x + (x=y)*0;
cout << y;
return 0;
}
which gives a result of 20, because the value of y is assigned to x since the bracket is executed first according to the Operator Precedence Table.
VB.NET:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim x As Integer = 10
Dim y As Integer = 20
y = x + (x = y) * 0
MsgBox(y)
End Sub
which instead gives a result of 10.
What is the reason for this difference?
What is the order of execution of operators in VB.NET?
Unlike in C++, VB.NET's = is not always an assignment. It can also be the equality comparison operator (== in C++) if it appears inside an expression. Therefore your two expressions are not the same. They are not even equivalent. The VB.NET code does not do what you might think it does.
First to your C++ code: Like you're saying, the assignment x=y happens first; thus your code is roughly equivalent to this: (It seems that was incorrect; see Jens' answer.) Since you end up with y being 20, it is likely that your C++ compiler evaluated your code as if you had written this:
int x = 10, y = 20;
x = y;
y = x + x*0; // which is equivalent to `y = 20 + 20*0;`, or `y = 20 + 0;`, or `y = 20;`
In VB.NET however, because the = in your subexpression (x=y) is not actually interpreted as an assignment, but as a comparison, the code is equivalent to this:
Dim x As Integer = 10
Dim y As Integer = 20
y = 10 + False*0 ' which is equivalent to `y = 10 + 0*0`, or `y = 10` '
Here, operator precedence doesn't even come into play, but an implicit type conversion of the boolean value False to numeric 0.
(Just in case you were wondering: In VB.NET, assignment inside an expression is impossible. Assignments must always be full statements of their own, they cannot happen "inline". Otherwise it would be impossible to tell whether a = inside an expression meant assignment or comparison, since the same operator is used for both.)
Your C++ snippet is undefined behavior. There is no sequence point between using x as the first argument and assigning y to x, so the compiler can evaluate the sub-expressions in any order. Both
First evaluate the left side: y = 10 + (x=y) * 0 -> y = 10 + (x=20) * 0 -> y = 10 + 20*0
First evaluate the right side: y = x + (x=20) * 0 -> y = 20 + 20 * 0
It is also generally a very bad style to put assignments inside expressions.
This answer was intended as a comment, but its length quickly exceeded the limit. Sorry :)
You are confusing operator precedence with evaluation order. (This is a very common phenomenon, so don't feel bad). Let me try to explain with a simpler example involving more familiar operators:
If you have an expression like a + b * c then yes, the multiplication will always happen before the addition, because the * operator binds tighter than + operator. So far so good? The important point is that C++ is allowed to evaluate the operands a, b and c in any order it pleases. If one of those operands has a side effect which affects another operand, this is bad for two reasons:
It may cause undefined behavior (which in your code is indeed the case), and more importantly
It is guaranteed to give future readers of your code serious headaches. So please don't do it!
By the way, Java will always evaluate a first, then b, then c, "despite" the fact that multiplication happens before addition. The pseudo-bytecode will look like push a; push b; push c; mul; add;
(You did not ask about Java, but I wanted to mention Java to give an example where evaluating a is not only feasible, but guaranteed by the language specification. C# behaves the same way here.)
I walked through a C++ book and I got a statement like this long x = 32L and given statement as l or L suffix on an integer means the integer is a type long constant; but when I check using compiler as long x = 32L ; cout<<x; x = 45 ; cout<<x ; then there is no error or warning so what constant mean here? Isn't long const x = 32; ?
Whether or not 32L is const doesn't matter ; when you write long x = 32L; then x is a variable whose value is copied from 32. x is certainly not const. When you change x you are not changing the literal 32; you are putting a new value into the variable x's storage.
The technical term in C++ for 32 or 32L is a literal. However, people sometimes call them "constants". This is a bit confusing because it is nothing to do with what the keyword const does.
The only difference between 32 and 32L is that one is int and the other is long.
I think you're getting confused about what L is for. Consider a platform with 32 bit int and 64 bit long :
unsigned long i = 0xffffffff << 16;
This sets: i <- 0xffff0000 since 0xffffffff is implicitly an integer value, and the expression on the right is evaluated accordingly. On the other hand,
unsigned long i = 0xffffffffUL << 16;
yields: i <- ffffffff0000, as the expression is being evaluated as an unsigned long.
In order a variable to be constant, it should be accompanied by the const keyword.
For example:
const int a = 5;
a = 6; // error
Now what you have, is that you assign a constant value, i.e. 32 in a variable. The constant goes to the value, not to the variable.
You do for example:
a = 32L;
so the value you assign to the variable a is a constant, 32L.
If you did
for(int i = 0; i < 5; ++i)
a = i;
then the value you assign to variable a is not a constant.
I strongly suggests you to take a look at my relative question about the L that follows 32.
What is the difference between long x = 32L and long const x = 32 ?
The difference is that in the first, you can assign variable x a new value, where in the second you can not.
You are getting confused with the terms.
According to this statement:
int x = 32;
x is a variable of the int type, and 32 is a literal of int type.
You can never do 32 = 35 , but you can do x = 35 because x is not a constant.
According to this other statement:
const long y = 32L;
it means that y is a constant of type long and cannot be changed. Also, 32L is a literal of type long and it cannot be changed either.
You can never do y = 35L because y is a constant and its value has been already set.
Moreover, just like #MattMcNabb sad:
"The only difference between 32 and 32L is that one is int and the other is long."
tl;dr: Yes, you're right.
The book is calling it a "constant", but it is wrong; the correct term is "literal".
There is no way to modify the literal itself (which is probably why the book author used this term) but, once you use the literal to initialise long int x, x can be modified because it is not const.
You are right that long int const x would be the way to make the final "variable" actually be a constant.
I have a pointer which is defined as follows:
A ***b;
What does accessing it as follows do:
A** c = b[-1]
Is it an access violation because we are using a negative index to an array? Or is it a legal operation similar to *--b?
EDIT Note that negative array indexing has different support in C and C++. Hence, this is not a dupe.
X[Y] is identical to *(X + Y) as long as one of X and Y is of pointer type and the other has integral type. So b[-1] is the same as *(b - 1), which is an expression that may or may not be evaluated in a well-formed program – it all depends on the initial value of b! For example, the following is perfectly fine:
int q[24];
int * b = q + 13;
b[-1] = 9;
assert(q[12] == 9);
In general, it is your responsibility as a programmer to guarantee that pointers have permissible values when you perform operations with them. If you get it wrong, your program has undefined behaviour. For example:
int * c = q; // q as above
c[-1] = 0; // undefined behaviour!
Finally, just to reinforce the original statement, the following is fine, too:
std::cout << 2["Good morning"] << 4["Stack"] << 8["Overflow\n"];
I thought that my understanding of side effects in programming languages was OK.
I think this is a great definition from wikipedia:
"in addition to returning a value, it also modifies some state or has
an observable interaction with calling functions or the outside world."
However, I read this in the same link(yes, I know that is probably not the best place to look for examples):
"One common demonstration of side effect behavior is that of the
assignment operator in C++. For example, assignment returns the right
operand and has the side effect of assigning that value to a variable.
This allows for syntactically clean multiple assignment:"
int i, j;
i = j = 3;
Why do they consider that a side-effect? It is the same as two simple assignment statements to 2 local variables.
Thanks in advance.
You can use an assignment expression as a value:
double d = 3.5;
int x, y;
printf("%d", x = d); // Prints "3".
y = (x = d) * 5; // Sets y to 15.
double z = x = d; // Sets z to 3 (not 3.5).
The value produced by x = d, is its main effect. The changing of the value of x is a side effect.
If the state of the world, for example the value of a variable, is modified in a calculation, it's a side effect.
For example, j = 3 calculates 3, but it also modifies the value of j as a side effect.
A less trivial example: j += 3 calculates j + 3, but it also sets j to this new value.
The semantics of C muddle the waters: in C the main point of writing i = 1 is to get the side effect of the variable assignment; not calculating the value 1. The talk about assignments as side effects makes more sense with functional programming languages such as Haskell or Erlang, where variables can only be assigned once.
I would presume that to be because j = 3 has the intended effect of assigning the value 3 to j but also has the side effect of returning the value of j