Reputation: 363
Suppose i have:
class A
{
A(A& foo){ ..... }
A& operator=(const A& p) { }
}
...
A lol;
...
A wow(...)
{
return lol;
}
...
...
A stick;
stick = wow(...);
Then I'll get a compile error in the last line. But if I add 'const' before 'A&', its ok.
I want to know why. Where it's exactly the problem? I dont get why it should be const.
Language: C++
I edited... I think that change its relevant. That gives error.
Upvotes: 4
Views: 834
Reputation: 10969
The call to wow
results in a temporary object, an r-value. R-values can not be assigned to non-const references. Since your copy constructor accepts non-const references, you can not pass the result of the call to wow
directly to it. This is why adding the const
fixes the problem. Now the copy constructor accepts const references, which r-values bind to just fine.
Chances are, your copy constructor does not change the object it is copying, so the paramter should be passed by const-reference. This is how copy constructors are expected to work, except in specific, documented circumstances.
But as sbi points out in his answer, this copy constructor shouldn't be getting called at all. So while this is all true, it likely has nothing to do with your problem. Unless there is a compiler bug. Perhaps your compiler sees the two-step construction, and decided it'll cut out the middle man by converting A stick; stick = wow();
into A stick = wow();
But this would be a bug, as evidenced by the fact that it produces a compile error out of perfectly legal code. But without actual code, its impossible to say what's really happening. There should be several other errors before any issues with your copy constructor come up.
Upvotes: 1
Reputation: 224079
The following code compiles perfectly fine with both Comeau and VC9:
class A
{
public:
A() {}
A(A&){}
};
A lol;
A wow()
{
return lol;
}
int main()
{
A stick;
stick = wow();
return 0;
}
If this doesn't compile with your compiler, then I suspect your compiler to be broken. If it does, then that means you should have pasted the real code, instead of supplying a snippet that doesn't resemble the problem you see.
Upvotes: 1
Reputation: 264411
This function:
A wow(...)
{ ... }
returns an object of by value.
This means it is copied back to the point where the function was called.
This line:
stick = wow(...);
Does a copy construction on stick.
The value copied into stick is the value copied back from the function wow().
But remember that the result of the call to wow() is a temporary object (it was copied back from wow() but is not in a variable yet).
So now we look at the copy constructor for A:
A(A& foo){ ..... }
You are trying to pass a temporary object to a reference parameter. This is not allowed. A temporary object can only be bound to a const reference. There are two solutions to the problem:
1) Use a const reference.
2) Pass by value into the copy constructor.
Unfortunately if you use solution (2) you get a bit stuck as it becomes a circular dependency. Passing by value involves using the copy constructor so you enter an infinte loop. So your solution is to use pass by const reference.
Upvotes: 0
Reputation: 1300
I believe the problem you are mentioning is similar to:
c++, object life-time of anonymous (unnamed) variables
where the essential point is that in C++ anonymous-temporaries can not be passed by reference but only by const reference.
Upvotes: 1
Reputation: 523304
Not reproducible. Are you missing the default constructor, or forgot to make the constructors public
?
See http://www.ideone.com/nPsHj.
(Note that, a copy constructor can take an cv A&
argument with any const-volatile combination plus some default arguments. See §[class.copy]/2 in C++ standard.)
Edit: Interesting, g++-4.3 (ideone) and 4.5 (with -pedantic
flag) don't have the compile error, but g++-4.2 do complain:
x.cpp: In function ‘int main()’:
x.cpp:19: error: no matching function for call to ‘A::A(A)’
x.cpp:7: note: candidates are: A::A(A&)
Upvotes: 0