why copy constructor is called when passing temporary by const reference?
Asked Answered
B

3

24

I am passing an unnamed temporary object to a function defined with const ref parameter. The copy ctor of the class is private, and I get a compilation error. I don't understand why a copy constructor is called in this situation.

class A {
public:
  A(int i) {}
private:
  A(const A&) {}
};

void f(const A& a)
{
}

int main()
{
  f(A(1)); // <-- error here: 'A::A(const A&)' is private
}

As expected, when I change the main to:

A a(1);
f(a);

it works.

EDIT: the compiler is gcc 4.1.2

Bunkhouse answered 19/1, 2011 at 9:11 Comment(6)
Which compiler are you using?Lacielacing
VC++9 is happy to compile the first variant.Lacielacing
@sharptooth: gcc, I'll updateBunkhouse
@davka: gcc? which version? gcc-4.3.4 compiles it fine: ideone.com/7sZ17Verduzco
possible duplicate of Unexpected const reference behaviorTem
possible duplicate of Copy Constructor Needed with temp object.Thankyou
I
19

You can find the answer to your question in Copy Constructor Needed with temp object or go directly to http://gcc.gnu.org/bugs/#cxx%5Frvalbind

The C++ Standard says that a temporary object should be created in this context and its contents filled with a copy of the object we are trying to bind to the reference; it also says that the temporary copy can be elided, but the semantic constraints (eg. accessibility) of the copy constructor still have to be checked.

For further information, you can consult the following paragraphs of the C++ standard: [dcl.init.ref]/5, bullet 2, sub-bullet 1, and [class.temporary]/2.

Starting with GCC 4.3.0, GCC no longer gives an error for this case. This change is based on the intent of the C++ language committee. As of 2010-05-28, the final proposed draft of the C++0x standard permits this code without error.

Ioves answered 19/1, 2011 at 9:40 Comment(0)
C
24

The expression A(1) is an rvalue 5.2.3 [expr.type.conv].

In initializing a const reference (the function argument) with an expression that is an rvalue the compiler may create a temporary and copy the value of that expression to the temporary and bind that reference to that temporary. 8.5.3 [dcl.init.ref] / 5.

[...] The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.

Note that this behaviour is due to change in the next version of C++. In the new standard a const reference initialized from a class prvalue must be bound directly to the reference object; no temporary is permitted to be created in this case and a copy constructor is not used or required.

Claudetta answered 19/1, 2011 at 9:40 Comment(2)
thanks. your last paragraph explains why this does not happen in the newer version of gcc as per @Nawaz comment, correct?Bunkhouse
@davka: I believe that that is the reason, yes.Claudetta
I
19

You can find the answer to your question in Copy Constructor Needed with temp object or go directly to http://gcc.gnu.org/bugs/#cxx%5Frvalbind

The C++ Standard says that a temporary object should be created in this context and its contents filled with a copy of the object we are trying to bind to the reference; it also says that the temporary copy can be elided, but the semantic constraints (eg. accessibility) of the copy constructor still have to be checked.

For further information, you can consult the following paragraphs of the C++ standard: [dcl.init.ref]/5, bullet 2, sub-bullet 1, and [class.temporary]/2.

Starting with GCC 4.3.0, GCC no longer gives an error for this case. This change is based on the intent of the C++ language committee. As of 2010-05-28, the final proposed draft of the C++0x standard permits this code without error.

Ioves answered 19/1, 2011 at 9:40 Comment(0)
H
0

Because a(1) calls the constructor A(int i) and then A(const A&) is called in the call to void f(const A&).

Make the A(int i) constructor explicit and you should not face this error.

Edit: I think i misunderstood the question. I might delete this.

Hedron answered 19/1, 2011 at 9:25 Comment(8)
From the C++ standard §3.2 paragraph 2: A copy constructor is used even if the call is actually elided by the implementation.Tem
The copy constructor should conceptually not be called here, that's the point of the question. Passing by reference implies no creation of a new object, hence no copy.Lacielacing
Why the down-vote? It is actually correct, according to the standard.Tem
@dalle:The piece you quote is for RVO-like cases, not for the situation in the question.Lacielacing
@sharptooth: Even though the copy constructor isn't called, it is still used.Tem
@dalle:No, it is not used - the object is passed by reference, not by value. It would be used if the object was passed by value only, then perhaps RVO-like copy elision could take place and the piece you quote would kick in.Lacielacing
@sharptooth: My first reference to the C++ standard was incorrect, but see open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#391Tem
@dalle: I see now, in that cse it can be used and even called, but I wouldn't ever expect such behavior.Lacielacing

© 2022 - 2024 — McMap. All rights reserved.