Я могу понять, что компилятор выполняет copy-elision в приведенном ниже коде, поскольку конструкторы копирования и перемещения не вызываются в так называемом copy-initialization
, выполненном в main()
. См. живой пример.
#include <iostream>
struct S {
S() = default;
S(const S&) { std::cout << "copy ctor" << '\n'; }
S(S&&) { std::cout << "move ctor" << '\n'; }
};
int main() {
S s = S();
}
Но я не могу понять, почему код не компилируется, когда я удаляю конструктор перемещения, как показано ниже:
#include <iostream>
struct S {
S() = default;
S(const S&) { std::cout << "copy ctor" << '\n'; }
S(S&&) = delete;
};
int main() {
S s = S();
}
Я не могу найти ничего в §12.8/32 (N4140), что могло бы запретить использование или исключение конструктора копирования в данном случае. Это предложение привлекло мое внимание в §12.8/32, которое, по-видимому, указывает на то, что конструктор копирования должен был учитываться при разрешении перегрузки:
Если первое разрешение перегрузки завершилось неудачно или не было выполнено, или если тип первого параметра выбранного конструктора не является ссылкой rvalue на тип объекта (возможно, cv-квалифицированным), разрешение перегрузки выполняется снова, рассматривая объект как объект. значение.
Изменить
Из одного из комментариев TC ниже я понимаю, что когда копируемый объект обозначается значением r, компилятор , согласно §12.8/32, не рассматривает конструктор-копию как кандидата на копию, даже если копия в любом случае будет исключена. То есть конечным результатом будет создание объекта s
с конструктором по умолчанию. Вместо этого в этой ситуации Стандарт предписывает (где??) код быть неправильно сформированным. Если мое понимание этой схемы совершенно неверно, это не имеет для меня никакого смысла.
return
этот абзац применим только тогда, когда, среди прочего, копируемый объект обозначен lvalue.S()
не является lvalue. - person T.C.   schedule 02.08.2015=delete
не означает, что этой функции не существует. Если вы не хотите, чтобы функция существовала, просто не объявляйте ее. То есть=delete
означает, что при попытке использовать такую удаленную функцию компилятор должен выдать ошибку. - person Piotr Skotnicki   schedule 03.08.2015