What is the output of the following program?
#include <iostream>
using namespace std;
int main()
{
int a = 2, b = 4;
a++ = b;
cout << a << b;
return 0;
}
This is not legal C++ code.
The statement
a++ = b;
is not legal. Intuitively, you can only place something on the left-hand side of an assignment expression if it represents an object, not a value. For example, we can't write
x + y = z;
because x + y is a value, not an object. The same principle is at play in your code: the expression a++ is not something that can be written to, as it means "change a by adding one to it, then produce the value that a used to have."
The comments on your question talk about the formal terms that are used to describe what I'm referring to here as "values" and "something can be written to." These are formally called lvalues, rvalues, prvalues, etc., and it might be worth looking into these to learn more about what sorts of assignment statements are legal.
Related
why is it possible to change the value of the constant z in the C++ snippet below? What is the meaning of (int&) in the 5th line? Note that the addresses of x, y, z are different (cout << &x << &y << &z). Thank you very much!
int x = 2;
int y = 3;
const int z = x;
cout << z; // the result is 2
(int&) z = y;
cout << z; // the result is 3
Because in this case we have a cast on the left side of an assignment expression that tells to compiler we are forcing our identifier in order it behaves as a not read-only reference to its memory location, and since we are knowingly "forcing" a behaviour, compiler trust us and allows this assignment.
In some cases this is potentially dangerous, as when you assign the const identifier with a literal value, because it is not standard how compilers implement this initialization, in fact some compilers seems that replace the occurrences of identifiers with the literal values, as well as a macro expansion, so you have to pay a very close attention doing this operation.
This is a code for adding 3 objects of class Integer
#include <iostream>
using namespace std;
class Integer
{
int value;
public:
Integer(int i)
{
value = i;
};
int getValue()
{
return value;
}
friend Integer operator+(const Integer & a,const Integer & b)
{
Integer i(a.value+b.value);
return i;
}
};
int main()
{
Integer a(1), b(2), c(3);
Integer d = a + b + c; //****HERE****
cout << d.getValue() << endl;
return 0;
}
Can someone please explain why const is added to parameters in this case. If I remove const, during compilation I get invalid operands to binary operation error.
Adding to this question:
When I only add a and b without const, output is 3 without any errors. However, adding 3 a+b+c objects, I get an error. Why is that?
Let's say hypothetically we had written this function:
friend Integer operator+(Integer& a, Integer& b);
Stylistically, this isn't great because operator+ shouldn't be modifying its arguments. But let's say we don't care about that. Now, what happens when we try to do this:
Integer d = a + b + c;
This is grouped as (a+b)+c. The a+b subexpression will find our operator+(), which is a viable function because a and b are non-const lvalues of type Integer, and the result of that expression is an rvalue of type Integer.
The subsequent expression is {some rvalue Integer} + c. That expression we won't be able to find a viable function for. While c can bind to Integer&, the first argument cannot - you can't bind an rvalue to a non-const lvalue reference. So you'd have to write something like:
Integer tmp = a + b; // OK
Integer d = tmp + c; // also OK
but now we're introducing this extra name into our scope and an extra statement into our code just to get around the unviability of our function signature.
Because you're trying to bind a Temporary to a [non-const-]reference, which isn't allowed in C++.
In the code Integer d = a + b + c;, a + b is evaluated first, and creates a new temporary object which then gets evaluated against c. So the code then becomes Integer d = t<a+b> + c;. Because the first object is now a temporary, only three function signatures will accept it as a parameter: const Integer &, Integer, and Integer &&. The second is not advised because it will create a copy of the object (though, sometimes that's what you want!), and the latter isn't advised because it will refuse to accept persistent objects. The first option, then, is best, because it will accept any Integer object regardless of whether it's expiring or not.
Recommended Reading: What are rvalues, lvalues, xvalues, glvalues, and prvalues? It's very verbose, and will probably require several passes before you "get" it, but it's extremely valuable knowledge for any C++ programmer.
I'm currently trying to refactor some code which uses a primitive type into something which I can tuck setters and getters into them. I wanted to make the change to the underlying code transparent, and at first I though C++'s operator overloads would help me out there.
Let's suppose I want to make an "augmented int" type, for instance, that can be treated just like a regular int, but allows for further action wherever I assign to it, and just assignment - all other properties of an int, such as adding with +=, should be preserved.
At first I first though that if I encapsulated the int inside some struct, and filled out the operator= overloads, I'd be set, like in the following example:
#include<iostream>
typedef struct PowerInt{
int x;
PowerInt(){
cout << "PowerInt created\n";
x = 0;
}
~PowerInt(){
cout << "PowerInt destroyed\n";
}
void operator=(int other){
cout << "PowerInt received " << other << "\n";
this->x = other;
}
}PowerInt;
int main(){
PowerInt a;
a = 3;
return 0;
}
The code compiles and runs as expected, but as soon as I try making anything else a regular int could do, like cout << a, or a += 2, or even a simple int b = a; assignment the compiler complains about the operators << and += missing.
Fair enough; I then though that, at least for << and "assigment =", I could get by using some sort of "generic rvalue operator", or some kind of method which returns PowerInt.x wherever my a is used as an rvalue, automatically making expressions like int c = (a + 3); and if (a == 3) {} valid.
Problem is, I can't find a way to implement this idiom, and this mostly likely has to do with either my little understanding of how operator overloading works in C++, or some language feature I'm not yet aware of. Is it possible to accomplish what I'm trying here?
If you want your PowerInt to be convertible to a normal int you can create a user-defined conversion operator:
operator int() const
{
return x;
}
Any operator that's not defined for PowerInt will then use the operator defined for a normal int.
P.S The typedef struct isn't necessary in C++.
#include <iostream>
using namespace std;
int main() {
//int& a = 3; <- Doesn't compile. Expression must be lvalue.
const auto& c = 1 + 2; // c is a constant reference to an int. (?)
// compiles fine. 1+2 is a rvalue? what's going on?
cout << c << endl;
return 0;
}
I don't understand why the compiler wont raise a compilation error.
Since auto "forces" c to be a reference to a constant int, and references are refereed to lvalues, how come this works?
This would indeed not work without the const -- you would get a compilation error.
But the const is there, i.e. you are not going to modify what c is referencing.
For this case, there is additional wording in the standard that the temporary value c is referencing (the result of 1 + 2) will have its lifetime extended to the end of the lifetime of the reference.
This is quite unrelated to auto. It's the const that is making the difference here.
If I have for example a class with instance method and variables
class Foo
{
...
int x;
int bar() { return x++; }
};
Is the behavior of returning a post-incremented variable defined?
Yes, it's equivalent to:
int bar()
{
int temp = x;
++x;
return temp;
}
Yes it is ... it will return the x's value before incrementing it and after that the value of x will be + 1 ... if it matters.
It is defined.
It returns the value of x before incrementation. If x is a local(non-static) variable this post incrementation has no effect since local variables of a function cease to exist once the function returns. But if x is a local static variable, global variable or an instance variable( as in your case), its value will be incremented after return.
Yes.
In postincrement (x++) the value of x is evaluated (returned in your case) before 1 is added.
In preincrement (++x) the value of x is evaluated after 1 is added.
Edit: You can compare the definition of pre and post increment in the links.
Most programming languages, like C++, are recursive in the order that operations are carried out (I'm not making any implication about how the code is actually implemented by the compiler here). Compound operations that are composed of any well defined operations are themselves well defined, since each operation is carried out on a last-in, first-out basis.
Post-increment returns the value of the variable being incremented before incrementing it, so the return operation recieves that value. No special definition of this behavior has to be made.
I know this question is answered long before but here's why it is defined.
Compound operators are basically syntax sugar for functions.
If you're wondering how the increment happens after returning from the function, it doesn't. It happens just before the operator "function" returns the previous value.
For an integer, think of the post increment operator function defined like this:
int post_increment(int *n)
{
int temp = *n;
*n = *n + 1;
return temp;
}
I think it is defined but not preferred. It causes confusion to people. For example, the following code prints 1 instead of 2.
#include <iostream>
#include <cstdlib>
using namespace std;
int foo()
{
int i = 1;
return i++;
}
int main()
{
cout << foo() << endl;
return 0;
}