5

Let's say I have this class:

class Test
{
public:
    Test();
};

AFAIK, compiler provides default copy constructor and assignment operators, which assign every member of other instance to the current instance. Now I add move constructor and assignment:

class Test
{
public:
    Test();
    Test(Test&& other);
    Test& operator=(Test&& other);
};

Does this class still contain compiler-generated copy constructor and assignment operators, or I need to implement them?

Edit. This is my test:

class Test
{
public:
    Test(){}

    Test(Test&& other){}
    Test& operator=(Test&& other)
    {
        return *this;
    }

    int n;
    char str[STR_SIZE];
};

int main()
{
    Test t1;
    t1.n = 2;
    strcpy(t1.str, "12345");

    Test t2(t1);

    Test t3;
    t3 = t1;

    cout << t2.n << " " << t2.str << " " << t3.n << " " << t3.str << endl;

    return 0;
}

Prints 2 12345 2 12345. Compiler: VC++ 2010. According to this test, copy constructor and assignment are still here. Is this standard behavior, can I be sure that this will work on every C++ compiler?

Alex F
  • 42,307
  • 41
  • 144
  • 212

2 Answers2

7

From 12.8-7 Copying and moving class objects [class.copy]

If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor...

From 12.8-18

If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy constructor or a user-declared destructor...

According to this, since you have declared a move constructor and a move assignment operator, but no copy assignment operator, copy constructor or destructor, you do not get the implicitly generated copy constructor or assignment operator. The compiler gives you their declarations, but they are declared as deleted.

Here is a simplified version of your example:

struct Test
{
public:
    Test(){}
    Test(Test&& other){}
    Test& operator=(Test&& other) { return *this;}
};

int main()
{
  Test t1;
  Test t2(t1);
}

And the error produced by g++ 4.8.1

ctors.cpp:13:13: error: use of deleted function 'constexpr Test::Test(const Test&)'

Test t2(t1);

ctors.cpp:1:8: note: 'constexpr Test::Test(const Test&)' is implicitly declared as deleted because 'Test' declares a move constructor or move assignment operator

struct Test

(emphasis mine)

Community
  • 1
  • 1
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • Thanks. Please take a look at my question - it is edited. Does this mean, that VC++ compiler produces non-standard code? – Alex F Jan 09 '14 at 07:26
  • @AlexFarber Correct. FYI g++4.8.1 give me `ctors.cpp:30:15: error: use of deleted function 'constexpr Test::Test(const Test&)' Test t2(t1);` – juanchopanza Jan 09 '14 at 07:31
  • @AlexFarber According to the standard it should **not** compile. This is what g++ (see comment above) thinks, and in this case, it is right. – juanchopanza Jan 09 '14 at 07:36
  • @AlexFarber I added a simplified example, with the very useful gcc error message (these diagnostics have improved greatly in the last versions of gcc). – juanchopanza Jan 09 '14 at 07:48
  • @Alex : VC++ 2010 predates the C++11 standard, so it isn't necessarily "non-conformant", it just implemented early rough-drafts of some features. – ildjarn Jan 09 '14 at 07:55
  • 1
    @ildjarn Of course it's non-conformant. An implementation that does not behave as the standard requires is by definition non-conformant. Certainly it's ridiculous to expect a compiler released before the specification to conform to that specification, but that doesn't change the meaning of the term "non-conformant." – Casey Jan 09 '14 at 20:27
1

According to section 12.8 Copying and moving class objects of the C++ Standard

7 If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4).

18 If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted; otherwise, it is defined as defaulted (8.4).

So in your case and the copy constructor and the copy assignment operator are implicitly declared by the compiler but defined as deleted.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335