Почему деструктор "= default" отличается от неявно объявленного деструктора? - PullRequest
8 голосов
/ 20 сентября 2019

Итак, я прочитал этот пост:

Чем "= default" отличается от "{}" для конструктора и деструктора по умолчанию?

Что объясняет почему:

~Widget() = default;

Это не то же самое, что:

~Widget() {}

Однако верно также и то, что регистр "= default" отличается от неявно объявленного регистра.В некотором смысле = default на самом деле не дает значения по умолчанию, что довольно странно.

Рассмотрим следующую программу:

class A
{
public:
    A(std::string str)
    {
        m_str = str;
    } 

    ~A() = default;

    A(A const& rhs)
    {
        printf("Got copied\n");
        m_str = rhs.m_str;
    }

    A(A&& rhs)
    {
        printf("Got moved\n");
        m_str = std::move(rhs.m_str);
    }

    std::string m_str;
};

class B 
{
public:
    B(std::string test) : m_a(test)
    {
    }

    ~B() = default;

    A m_a;
};

int main()
{
    B b("hello world");
    B b2(std::move(b));

    return 0;
}

При запуске этой программы будет напечатано «Got copyied»,если вы не закомментируете дефолтную ~ B (), в этом случае будет напечатано «Got Moveed».Так почему это?Я думаю, что «= default» довольно запутанно, учитывая, что и этот, и неявно объявленный деструктор должны создавать «тривиальные деструкторы».

1 Ответ

6 голосов
/ 20 сентября 2019

Неявно определенный конструктор перемещения для B создается только в том случае, если

  • нет объявленных пользователем конструкторов копирования;
  • нет объявленных пользователем операторов назначения копирования;
  • нет объявленных пользователем операторов назначения перемещения;
  • нет объявленных пользователем деструкторов;

Теперь, когда вы говорите ~B() = default;, хотя вы все еще получаете деструктор по умолчанию, он теперь также считается объявленным пользователем, и, следовательно, не будет неявно определенного конструктора перемещения.

...