简体   繁体   中英

Incomplete verbosity of default definitions declarations

In Stroustrup's Tour of C++ he mentions:

If you are explicit about some defaults, other default definitions will not be generated.

However, this doesn't seem to be the case with gcc 4.9.1. Take for example:

#include <iostream>
using namespace std;

struct A 
{
    int data;
    A() = default;
    A(const A&) = default;
};

int main() 
{

  A a;
  a.data = 10;
  A b(a);
  A c;
  c = a;

  cout<<b.data<<endl;
  cout<<c.data<<endl;
  return 0;
}

It compiles and gives the expected output. ie the default assignment operator has been generated.

Did I misunderstand Stroustrup's comment?

Firstly, your code doesn't use the class's assignment operator, so it doesn't demonstrate that it exists. However, adding a use of it

c = a;

will work, so the question still stands.

It's not the case that declaring any special function prevents all other special functions from being generated, which seems to be how you're interpreting the quote. Declaring some will inhibit some others. Not having read the book to put the quote in context, I can't say whether or not it's misleading.

The rules are, roughly:

  • declaring any constructor will prevent an implicit default constructor;
  • declaring a move constructor or move-assignment operator will prevent an implicit copy constructor and copy-assignment operator;
  • declaring a destructor, copy constructor or copy-assignment operator will prevent an implicit move constructor and move-assignment operator;

That's a simplification; there are more nuances and exceptions. Read the language specification if you want the gory details.

Those declarations are currently generated by default (which is why the code you provided works), but this behavior is subject to be removed at any time in further revisions to the C++ standard (deprecated).

In Stroustrup's C++11 FAQ , he states

If any move, copy, or destructor is explicitly specified (declared, defined, =default, or =delete) by the user, no move is generated by default.

That is pretty self explanatory. However , he goes on to say that...

If any move, copy, or destructor is explicitly specified (declared, defined, =default, or =delete) by the user, any undeclared copy operations are generated by default, but this is deprecated, so don't rely on that.

He then lists a few examples:

class X1 {
    X1& operator=(const X1&) = delete;  // Disallow copying
};

This implicitly also disallows moving of X1s. Copy initialization is allowed, but deprecated.

class X2 {
    X2& operator=(const X2&) = delete;
};

This implicitly also disallows moving of X2s. Copy initialization is allowed, but deprecated.

class X3 {
    X3& operator=(X3&&) = delete;   // Disallow moving
};

This implicitly also disallows copying of X3s.

class X4 {
    ~X4() = delete; // Disallow destruction
};

This implicitly also disallows moving of X4s. Copying is allowed, but deprecated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM