Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does r-value reference to object generator call require copy constructor?

I'm getting trouble with the following code with Visual Studio 2010 C++.

makeA() is just an object generator idiom in C++ (like std::make_pair)

#include <stdio.h>

struct A{ // 7th line
    A() {}
    A(A &&) {printf("move\n");}
    ~A() {printf("~A();\n");}
private:
    A(const A &) {printf("copy\n");} // 12th line
};

A makeA()
{
    return A();
}

int main()
{
    A &&rrefA(makeA()); // 22nd line
    return 0;
}

Error message

2>d:\test.cpp(22): error C2248: 'A::A' : cannot access private member declared in class 'A'
2>          d:\test.cpp(12) : see declaration of 'A::A'
2>          d:\test.cpp(7) : see declaration of 'A'
2>

I expect makeA() to call both A() constructor and A(A &&) constructor, and 22nd line to call makeA() and nothing else. (If without RVO) The compiler should not require A(const A &) constructor to be accessible, am I right?

Can you tell me what's wrong with the code?

With recent version of g++, 'g++ -std=c++0x' and 'g++ -std=c++0x -fno-elide-constructors' compiles the code without any error.

like image 724
kcm1700 Avatar asked Jun 04 '12 07:06

kcm1700


People also ask

Why is object's reference passed to the copy constructor instead of the object itself?

It is necessary to pass object as reference and not by value because if you pass it by value its copy is constructed using the copy constructor. This means the copy constructor would call itself to make copy. This process will go on until the compiler runs out of memory.

Why do you need to use a reference in the argument to the copy constructor?

When we create our own copy constructor, we pass an object by reference and we generally pass it as a const reference. One reason for passing const reference is, we should use const in C++ wherever possible so that objects are not accidentally modified.

Does passing by reference call copy constructor?

The point of "pass by reference" is to not make a copy as soon as Employee constructor is called, but only when you choose to initialize one of Employee's member with the Date passed.

Why do we need move constructor?

A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying.


1 Answers

It's a bug in the optimizer. The compiler attempts to ellide the move, but is only programmed to ellide a copy constructor- which requires a copy constructor to exist to be ellided in the first place.

I don't recall what (if any) the fix for this error is, but it might have been fixed in SP1.

like image 89
Puppy Avatar answered Oct 13 '22 00:10

Puppy