RVO и конструктор удаленных перемещений в C++14


Я узнал о (N)RVO в течение последних нескольких дней. Как я читал на cppreference в статье copy elision, для C++14:

... компиляторам разрешено, но не обязательно пропускать построение объектов класса copy - and move (начиная с C++11), даже если конструктор copy/move (начиная с C++11) и деструктор имеют заметные побочные эффекты. Это оптимизация: даже если она имеет место и конструктор copy- / move - не вызывается, он все равно должен быть присутствует и доступен (как будто никакой оптимизации вообще не было), в противном случае программа плохо сформирована.

Таким образом, либо copy , либо move конструктор должен присутствовать и быть доступен. Но в коде ниже:

#include <iostream>

class myClass
{
public:
    myClass() { std::cout << "Constructor" << std::endl; }
    ~myClass() { std::cout << "Destructor" << std::endl; }

    myClass(myClass const&) { std::cout << "COPY constructor" << std::endl;}
    myClass(myClass &&) = delete;
};

myClass foo()
{
    return myClass{};
}

int main()
{
    myClass m = foo();
    return 0;
}

Я получил следующую ошибку: test.cpp: In function 'myClass foo()': test.cpp:15:17: error: use of deleted function 'myClass::myClass(myClass&&)' return myClass{};. Я получаю эту ошибку, даже если я не вызываю foo() из main(). Та же проблема и с НРВО.

Следовательно, конструктор перемещения всегда требуется, не так ли? (хотя копии нет, я ее проверил)

Я этого не делаю. понять, где компилятору нужен конструктор перемещения. Я только предполагаю, что это может потребоваться для построения временной переменной, но это звучит сомнительно. Неужели кто-то знает ответ?

О компиляторе: я пробовал его на g++ и VS компиляторах, вы можете проверить его онлайн: http://rextester.com/HFT30137 .

P.S. Я знаю, что в стандарте C++17 РВО обязано. Но НРВО-нет, поэтому я хочу изучить, что здесь происходит, чтобы понять, когда я смогу использовать НРВО.

1 5

1 ответ:

Цитируется из cppreference:

Удаленные функции

Если вместо тела функции используется специальный синтаксис = delete ;, то функция определяется как delete.

...

Если функция перегружена, сначала происходит разрешение перегрузки, и программа плохо формируется только в том случае, если была выбрана удаленная функция.

Это не одно и то же, если вы явно определяете конструктор перемещения для удаления. Здесь из-за наличия этого удаленного конструктора перемещения, хотя конструктор копирования может совпадать, конструктор перемещения лучше, таким образом, конструктор перемещения выбирается во время разрешения перегрузки.

Если вы удалите явный delete, то будет выбран конструктор копирования и ваша программа будет компилироваться.