Присвоение из rvalue разрешено, когда оператор присваивания явно удален?

Рассмотрим следующий код, который компилируется в Clang, GCC и VS 2015 (онлайн пример):

#include <utility>

class S
{
public:
S(int x) : i(x) { }
~S() { }

S(S&&)  = default;

S(const S& )            = delete;
S& operator=(S&&)       = delete;
S& operator=(const S&)  = delete;

private:
int i;
};

S GetS()
{
// This is a contrived example with details elided. Assume
// there's a reason in the actual use case for returning via
// std::move.
return std::move( S(999) );
}

int main()
{
S tmp = GetS(); // <-- Assignment allowed even though assignment operator is deleted?

return 1;
}

Мне неясно, почему линия

S tmp = GetS();

компилирует, выполняя конструктор перемещения вместо оператора присваивания перемещения.

Я знаю, что RVO позволяет исключить конструкцию и назначение в качестве оптимизации, но, насколько я понимаю, явное удаление оператора должно привести к сбою компиляции, если этот оператор явно используется в коде.

Есть ли какое-то предложение в спецификации C ++ 11, которое позволяет компилятору преобразовывать инициализацию присваивания в конструкцию копии, даже если операторы присваивания для типа были явно удалены?

1

Решение

Это потому, что это не задание:

S tmp = GetS();

это называется копия инициализация и вызывает конструктор перемещения, который вы явно задали по умолчанию.

По сути, оператор присваивания вызывается только для объекта, который уже существует. tmp еще не существует, это утверждение инициализирует его. Таким образом, вы вызываете конструктор.

Обратите внимание, что происходит внутри из GetS() не влияет на правила, как tmp построен GetS() это значение в любом случае.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]