Copy constructor, return by value and const references

J

Jan Lellmann

Hello,

could anyone explain to me why the following code fails to compile?

----

#include <iostream>
using namespace std

class A {
private:
friend A createA(); // private default constructor
A() { cout << "default constructor" << endl; };
A(const A& from) { // private copy constructor
cout << "copy constructor" << endl;
}
public:
int get() {
return 1;
}
};


A createA() {
return A();
}

int main(int, char**)
{
createA().get(); // this compiles
const A& ref(createA()); // "error: A::A(const A&) is private"
}

----

The error is the same with g++ and VC++. When the copy constructor is
declared public instead, the code compiles but the copy constructor never
gets called -- why?

Regards,
Jan
 
A

Alex

Hello,

could anyone explain to me why the following code fails to compile?

----

#include <iostream>
using namespace std

class A {
private:
friend A createA(); // private default constructor
A() { cout << "default constructor" << endl; };
A(const A& from) { // private copy constructor
cout << "copy constructor" << endl;
}
public:
int get() {
return 1;
}

};

A createA() {
return A();

}

int main(int, char**)
{
createA().get(); // this compiles
const A& ref(createA()); // "error: A::A(const A&) is private"

}

----

The error is the same with g++ and VC++. When the copy constructor is
declared public instead, the code compiles but the copy constructor never
gets called -- why?

Regards,
Jan
copy constructor is called "return A() " runs
A createA() {
return A();


}
 
J

Jan Lellmann

copy constructor is called "return A() " runs
A createA() {
return A();


}

Yes, that's what I would have guessed at first. But createA() is a "friend"
so it has access to the copy constructor, which can be seen from the fact
that the "createA().get();" line compiles.

Also, as I wrote the copy constructor will not get called (you can check by
making the copy constructor public and looking at the output).

Regards,
Jan
 
L

LR

Jan said:
Hello,

could anyone explain to me why the following code fails to compile?

----

#include <iostream>
using namespace std

class A {
private:
friend A createA(); // private default constructor
A() { cout << "default constructor" << endl; };
A(const A& from) { // private copy constructor
cout << "copy constructor" << endl;
}
public:
int get() {
return 1;
}
};


A createA() {
return A();
}

int main(int, char**)
{
createA().get(); // this compiles
const A& ref(createA()); // "error: A::A(const A&) is private"
}

----

The error is the same with g++ and VC++. When the copy constructor is
declared public instead, the code compiles but the copy constructor never
gets called -- why?


If I've read the standard correctly, I think that section 12.2 says that
a copy ctor doesn't have to be called here, it can be elided by the
compiler. But if the copy ctor isn't called the compiler still has to
apply the rules as if it were called.

LR
 
A

Alex

If I've read the standard correctly, I think that section 12.2 says that
a copy ctor doesn't have to be called here, it can be elided by the
compiler. But if the copy ctor isn't called the compiler still has to
apply the rules as if it were called.

LR- éšè—被引用文字 -

- 显示引用的文字 -

yep, :D
 
S

SG

using namespace std

class A {
private:
     friend A createA(); // private default constructor
     A() { cout << "default constructor" << endl; };
     A(const A& from) {  // private copy constructor
         cout << "copy constructor" << endl;
     }
public:
     int get() {
         return 1;
     }
};

A createA() {
     return A();
}

int main(int, char**)
{
     createA().get();         // this compiles
     const A& ref(createA()); // "error: A::A(const A&) is private"
}

The standard allows the compiler to copy a temporary to another
temporary before binding it to a reference-to-const. Obviously you
need to have a public copy ctor for that. C++0x will get rid of this
rule and make your program well-formed. Some compilers don't even
complain about these things (g++) because they always *directly* bind
a temporary to a ref-to-const.

Cheers,
SG
 
S

SG

The standard allows the compiler to copy a temporary to another
temporary before binding it to a reference-to-const. Obviously you
need to have a public copy ctor for that. C++0x will get rid of this
rule and make your program well-formed. Some compilers don't even
complain about these things (g++) because they always *directly* bind
a temporary to a ref-to-const.


To be specific: 8.5.3 [dcl.init.ref] (Initializers, references). The
bullet point for class-type rvalues:

— If the initializer expression is an rvalue, with T2 a class
type, and “cv1 T1” is reference-compatible with “cv2 T2,” the
reference is bound in one of the following ways (the choice is
implementation-defined):

— The reference is bound to the object represented by the
rvalue (see 3.10) or to a subobject within that object.

— A temporary of type “cv1 T2” [sic] is created, and a
constructor is called to copy the entire rvalue object into
the temporary. The reference is bound to the temporary or to
a subobject within the temporary.

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


In C++0x compilers are forced to go with the first option:

— If the initializer expression is an rvalue, with T2 a class
type, and “cv1 T1” is reference-compatible with “cv2 T2,” the
reference is bound to the object represented by the rvalue
(see 3.10) or to a sub-object within that object.
 
J

Jan Lellmann

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

Weird, but thanks for the precise explanation.

Best Regards,
Jan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,808
Messages
2,569,684
Members
45,443
Latest member
sol

Latest Threads

Top