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 ответ:
Цитируется из cppreference:
Удаленные функции
Если вместо тела функции используется специальный синтаксис = delete ;, то функция определяется как delete.
...
Если функция перегружена, сначала происходит разрешение перегрузки, и программа плохо формируется только в том случае, если была выбрана удаленная функция.
Это не одно и то же, если вы явно определяете конструктор перемещения для удаления. Здесь из-за наличия этого удаленного конструктора перемещения, хотя конструктор копирования может совпадать, конструктор перемещения лучше, таким образом, конструктор перемещения выбирается во время разрешения перегрузки.
Если вы удалите явный
delete
, то будет выбран конструктор копирования и ваша программа будет компилироваться.