Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Copy constructor, return by value and const references

Reply
Thread Tools

Copy constructor, return by value and const references

 
 
Jan Lellmann
Guest
Posts: n/a
 
      11-09-2009
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
 
Reply With Quote
 
 
 
 
Alex
Guest
Posts: n/a
 
      11-09-2009
On 11月9日, 上午9时16分, Jan Lellmann <(E-Mail Removed)> wrote:
> 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();


}
 
Reply With Quote
 
 
 
 
Jan Lellmann
Guest
Posts: n/a
 
      11-09-2009
> 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
 
Reply With Quote
 
LR
Guest
Posts: n/a
 
      11-09-2009
Jan Lellmann wrote:
> 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
 
Reply With Quote
 
Alex
Guest
Posts: n/a
 
      11-09-2009
On 11鏈9鏃, 涓嬪崍1鏃45鍒, LR <(E-Mail Removed)> wrote:
> Jan Lellmann wrote:
> > 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- 闅愯棌琚紩鐢ㄦ枃* -
>
> - 鏄剧ず寮曠敤鐨勬枃* -


yep,
 
Reply With Quote
 
SG
Guest
Posts: n/a
 
      11-09-2009
On 9 Nov., 02:16, Jan Lellmann wrote:
>
> 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
 
Reply With Quote
 
SG
Guest
Posts: n/a
 
      11-09-2009
On 9 Nov., 09:26, SG wrote:
> On 9 Nov., 02:16, Jan Lellmann wrote:
>
> > 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.



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 揷v1 T1 is reference-compatible with 揷v2 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 揷v1 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 揷v1 T1 is reference-compatible with 揷v2 T2, the
reference is bound to the object represented by the rvalue
(see 3.10) or to a sub-object within that object.


> Cheers,
> SG

 
Reply With Quote
 
Jan Lellmann
Guest
Posts: n/a
 
      11-09-2009
> 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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
is const necessary in eg int compar(const void *, const void *) lovecreatesbeauty@gmail.c0m C Programming 26 11-10-2008 09:47 PM
Overload resolution and copy constructors that take non-const references Anthony Williams C++ 6 05-09-2008 10:28 AM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM
Casting int'** to 'const int * const * const' dosn't work, why? Jonas.Holmsten@gmail.com C Programming 11 07-01-2007 06:16 PM
const references -- how to document intent of const qualification Andrew R. Thomas-Cramer Java 8 07-11-2003 05:01 PM



Advertisments