This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How come a non-const reference cannot bind to a temporary object?
This program:
int fun()
{
return 1;
}
int main()
{
const int& var = fun();
return 0;
}
My question is why I must put a const befor the var definition? If not ,g++ will give me an error ,goes something like "invalid initialization of non-const reference of type ‘int&’ from a temporary of type ‘int’."
what is the 'const' for ?
In this situation you need const because reference initialization requires a variable with an address, not simply a value. Therefore the compiler must create an anonymous variable which you cannot access other than through the reference; the compiler does not want you to access the variable that you did not declare.
If you would declare the variable explicitly, const would be unnecessary:
int tmp = fun();
int &var(tmp);
Related
This question already has answers here:
Why can a const method take a non const reference?
(2 answers)
Closed 2 years ago.
Consider the following code:
#include <iostream>
class ObjectCalculator {
public:
struct Object {
int id = 0;
};
void setObject(Object& object) const {
object.id = 1;
}
Object m_object;
};
int main() {
ObjectCalculator objCalc{};
std::cout << objCalc.m_object.id << std::endl;
objCalc.setObject(objCalc.m_object);
std::cout << objCalc.m_object.id << std::endl;
return 0;
}
I thought this this line should throw an error during compilation since the internal variable is changed via const method setObject:
objCalc.setObject(objCalc.m_object);
but the code compiles with no errors and outputs:
0
1
Could you please clarify why const does not have effect in this case?
const related to the members of the class.
You modifying the method argument, so it can be changed, regardless of const.
const after method applied to the implicit first method argument this, through which all class members accessed.
cppreference
A non-static member function can be declared with a const, volatile,
or const volatile qualifier (this qualifier appears after the
parameter list in the function declaration). Differently cv-qualified
functions have different types and so may overload each other.
In the body of a cv-qualified function, the this pointer is
cv-qualified, e.g. in a const member function, only other const member
functions may be called normally. (A non-const member function may
still be called if const_cast is applied or through an access path
that does not involve this.)
The const qualifier is to tell that the function does not modify this object.
By passing the object to modify as an argument you don't modify this, you modify the object passed as an argument.
If you tried to modify m_object in the function, you would get the error you expected.
This question already has answers here:
Why not non-const reference to temporary objects? [duplicate]
(4 answers)
Closed 6 months ago.
For some reason I didn't manage to find this exact question. Why is it allowed to bind an rvalue to const lvalue reference, although it is impossible to to the same without the const?
I do understand that the lifetime of the rvalue gets an extension somehow (in the first case) , but if so, why would the compiler disallow changing that 'rvalue', which is not really a temporary object anymore.
For example, consider the following code:
int main(){
int &i=3; //produces error
const int&j =3; //compiles
return 1;
}
You may find the following article useful:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/N0345.pdf
I might be entirely wrong here, but this is how I rationalise it. An rvalue is constant, it cannot be changed. you cannot change the integer 5, fact. So when you bind the references the lvalue will have to be const. Otherwise your compiler will throw an error:
obj & a1 = bar();
invalid initialization of non-const reference of type ‘obj&’ from an rvalue of type ‘obj’
using g++
The only way to safely bind an rvalue to an lvalue is either by marking the lvalue as const, or using a mutable rvalue reference && (introduced in C++11 believe?)
struct obj {
};
obj bar() {
obj x;
return x;
}
int main() {
const obj & a1 = bar();
obj && a2 = bar();
return 0;
};
If you're asking about
void f(const int&);
f(1);
versus
void g(int&);
g(1);
the answer is to think about what happens if g looks like this:
void g(int& r) {
++r;
}
The name r-value comes from the right-value: which (roughly) means things that are on the right side of a x=y kind of statement. It is like: it can be read from, but it may not be suitable to be written on. For example a numeric literal can be on the right side (a=3) but it does not make sense to be on the left side (3=a).
With this reasoning, it looks logical to me why it is allowed to make const l-value references to r-values but not allowed to make non-const references.
This question already has answers here:
Why not non-const reference to temporary objects? [duplicate]
(4 answers)
Closed 6 years ago.
Lets say I have class A:
class A {
int i;
public:
A(){};
A(int i){this->i=i;};
};
And a simple test function:
void test(const A &a){...}
Now, if I do:
int main()
{
test(2);
}
It compiles and it will call the A(int i) constructor. But when I change the argument to be non-const: void test(A &a) I get a compilation error.
What is the difference between those cases, why the first one is allowed and the second not, and what actually happens in the initialization of the first case?
The difference between the two cases is that C++ compiler is allowed to create temporary objects to be passed to functions accepting a const references, but functions accepting non-const references must be provided with actual objects.
When you call test(2) what actually happens is this:
A hidden(2);
test(hidden);
The compiler creates hidden object, initializes it with 2, and passes the result to test. Since test is guaranteed to not modify A, this is fine.
When test does not provide such guarantee: imagine test that sets a new value:
void test(A& a) {
a.i++; // let's pretend "i" is public
}
If you call test with an actual object, i.e. A a(3); test(a); you can harvest the result of the update from a after test return. Calling test(2), on the other hand, gives you no way to access the result of an update. This indicates a potential error in the logic, so the compiler treats it as an error.
This is an interesting case. using const you can bind a reference to an rvalue. A more simpler example is below.
int get_num()
{
return 2;
}
int main(){
int& p = get_num(); // This is a compiler error. Can't create a non-const reference to an rvalue
const int& q = get_num(); // this will work. Can create const reference to an rvalue
}
This is part of the c++ standard.
what actually happens in the initialization of the first case?
In the 1st case, a temporary A will be constructed implicitly by A::A(int) and then bound to the lvalue reference to const. The effect of test(2); is same as test(A(2));.
Temporary can't be bound to lvalue reference to non-const, that's why the 2nd case failed.
This question already has answers here:
Returning non-const reference from a const member function
(3 answers)
Closed 7 years ago.
I have a class with a list as member, and a getter on this list:
class A
{
public:
const std::list<int*>& get() const {
return list;
}
private:
std::list<int*> list;
};
Why the get function has to return a const std::list and not just an std::list ?
Otherwise I get this error :
error: invalid initialization of reference of type 'std::list&'
from expression of type 'const std::list'
The problem is that the function get is declared as const:
const std::list<int*>& get() const
// ^
, so list is considered as a const inside the function.
Hence the attempt to return it as a non-const reference fails.
Problem
The issue here is that get is const qualified, therefore it can only return a const reference to one of its member objects. If you want to return a non-const reference then you have to make get non const-qualified.
If you think about this also makes sense from the point of view of const-correctness: if you are allowed to return a non-const reference to a member object from a const qualified member function, then you can effectively modify a constant object via that reference, for example via:
A const a(...);
std::list<int*> ref = a.get(); // const qualified but returning non const reference
ref.clear(); // wiped out contents of list in `a`
Possible solutions
I'd recommend to provide both overloads as follows:
const std::list<int*>& get() const { return list; }
std::list<int*>& get() { return list; }
At this point it might be worth considering to just make the list public, depending on the context:
struct A {
std::list<int*> list;
};
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
typedef and containers of const pointers
Why is the code emitting an error?
int main()
{
//test code
typedef int& Ref_to_int;
const Ref_to_int ref = 10;
}
The error is:
error: invalid initialization of non-const reference of type ‘int&’ from a temporary of type ‘int’
I read the post on prolonging the lifetime of temporaries which says that temporaries can be bound to references to const. Then why is my code not getting compiled?
Here the type of ref is actually reference to int and not const reference to int. The const qualifier is ignored.
$8.3.2 says
Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a typedef (7.1.3) or of a template type argument (14.3), in which case the cv-qualifiers are ignored.
const Ref_to_int ref; is equivalent to int& const ref; and not const int& ref.
Mixing const with a typedef doesn't work the way you're thinking; see this question for more info. These two lines are equivalent:
const Ref_to_int ref;
int& const ref;
You're looking for:
const int& ref;
One way to fix it is to include it in the typedef itself (although you should probably rename it then):
typedef const int& Ref_to_int;
You can't add additional specifiers to a typedef. It doesn't work like a macro.
Your code is effectively
int& const ref = 10; // error
which isn't valid.