Why do we need to use virtual ~A() = default; instead of virtual ~A() {} in C++11?

后端 未结 3 584
隐瞒了意图╮
隐瞒了意图╮ 2020-12-23 19:26

In Stack Overflow post Checking the object type in C++11, I have the comment:

In C++11 you\'ll actually want to do virtual ~A() = defau

3条回答
  •  天涯浪人
    2020-12-23 20:26

    In this post https://stackoverflow.com/a/17204598/260127, I have the comment:

    In C++11 you'll actually want to do virtual ~A() = default; Otherwise, you'll lose the implict move constructors.

    The comment is incorrect.

    Even defaulted, that destructor is "user-declared" (though note that it is not also "user-provided").

    #include 
    
    struct Helper
    {
        Helper() {}
        Helper(const Helper& src) { std::cout << "copy\n"; }
        Helper(Helper&& src)      { std::cout << "move\n"; }
    };
    
    struct A
    {
        virtual ~A() {}
        Helper h;
    };
    
    struct B
    {
        virtual ~B() = default;
        Helper h;
    };
    
    struct C
    {
        Helper h;
    };
    
    
    int main()
    {
        {
            A x;
            A y(std::move(x));   // outputs "copy", because no move possible
        }
    
        {
            B x;
            B y(std::move(x));   // outputs "copy", because still no move possible
        }
    
        {
            C x;
            C y(std::move(x));   // outputs "move", because no user-declared dtor
        } 
    }
    

    Live demo:

    + g++-4.8 -std=c++11 -O2 -Wall -pthread main.cpp
    + ./a.out
    copy
    copy
    move

    So you haven't "lost" anything — there was no move functionality there to begin with!

    Here is the standard passage that prohibits an implicit move constructor in both cases:

    [C++11: 12.8/9]: If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

    • X does not have a user-declared copy constructor,
    • X does not have a user-declared copy assignment operator,
    • X does not have a user-declared move assignment operator,
    • X does not have a user-declared destructor, and
    • the move constructor would not be implicitly defined as deleted.

    Bootnote

    It wouldn't hurt if a future version of the standard actually listed the precise meanings of terms such as "user-declared". There is, at least, this:

    [C++11: 8.4.2/4]: [..] A special member function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. [..]

    One may assume the distinction here by implication.

提交回复
热议问题