fsdfa
fsdfa

Reputation: 363

Copy constructor, why in return by value functions

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

Answers (5)

Dennis Zickefoose
Dennis Zickefoose

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

sbi
sbi

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

Loki Astari
Loki Astari

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

Akanksh
Akanksh

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

kennytm
kennytm

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

Related Questions