Информация об изменениях

Сообщение Re[7]: Почему нельзя писать void ctor(); от 28.04.2017 21:37

Изменено 28.04.2017 21:41 N. I.

Re[7]: Почему нельзя писать void ctor();
uzhas:

U>а можно пояснить, почему нет вызова конструктора?


A{1024} выполняет aggregate initialization, которая инициализирует объект типа A без привлечения конструкторов. По новым правилам результат A{1024}, return object функции f, результат преобразования A(f()) и obj — это один и тот же объект; никаких дополнительных объектов типа A нигде не создаётся.

Отдельного упоминания заслуживает вот такой пример:

#include <iostream>

void *ptr;

struct X
{
    X() { ptr = this; }
};

struct A
{
    A(A &&) = delete;
    X x;

private:
    A(A &) = default;
};

A f()
{
    return A{};
}

int main()
{
    A obj = A(f());
    std::cout << (&obj == ptr) << std::endl;
    std::cout << &obj << std::endl;
    std::cout << ptr << std::endl;
}

Здесь наличие конструктора A(A &) позволяет делать копию объекта при возврате функции (то, что конструктор приватный и не может принимать rvalue типа A, в данном случае роли не играет), отчего равенство (&obj == ptr) может не соблюдаться. Хотя gcc 8 пока что имеет наглость создавать копию и при полном отсутствии non-deleted copy/move-конструкторов, что, насколько я вижу, является нарушением правил.

U>вот тут видно, что деструктор вызывается: https://wandbox.org/permlink/UB1kdA5fS0h2Mo5Q

U>значит, был вызов и конструктора?

Объект классового типа может быть инициализирован без использования конструктора, это никак не мешает ему быть уничтоженным с помощью деструктора.
Re[7]: Почему нельзя писать void ctor();
uzhas:

U>а можно пояснить, почему нет вызова конструктора?


A{1024} выполняет aggregate initialization, которая инициализирует объект типа A без привлечения конструкторов. По новым правилам результат A{1024}, return object функции f, результат преобразования A(f()) и obj — это один и тот же объект; никаких дополнительных объектов типа A нигде не создаётся.

Отдельного упоминания заслуживает вот такой пример:

#include <iostream>

void *ptr;

struct X
{
    X() { ptr = this; }
};

struct A
{
    A(A &&) = delete;
    X x;

private:
    A(A &) = default;
};

A f()
{
    return A{};
}

int main()
{
    A obj = A(f());
    std::cout << (&obj == ptr) << std::endl;
    std::cout << &obj << std::endl;
    std::cout << ptr << std::endl;
}

Здесь наличие конструктора A(A &) позволяет делать копию объекта при возврате из функции f (то, что конструктор приватный и не может принимать rvalue типа A, в данном случае роли не играет), отчего равенство (&obj == ptr) может не соблюдаться. Хотя gcc 8 пока что имеет наглость создавать копию и при полном отсутствии non-deleted copy/move-конструкторов, что, насколько я вижу, является нарушением правил.

U>вот тут видно, что деструктор вызывается: https://wandbox.org/permlink/UB1kdA5fS0h2Mo5Q

U>значит, был вызов и конструктора?

Объект классового типа может быть инициализирован без использования конструктора, это никак не мешает ему быть уничтоженным с помощью деструктора.