class A {};
int main() {
A() = A();
return 0;
}
Почему этот код компилируется? Не должно быть какой-то ошибки, что слева от оператора присваивания должно быть помещено lvalue? Является ли A () lvalue? версия g ++ 4.7
Для встроенных типов вы будете правы: встроенный оператор присваивания требует изменяемого lvalue с левой стороны.
Однако здесь используется не встроенный оператор, а перегрузка, неявно объявленная классом. Это функция-член, эквивалентная
A().operator=(A());
и функции-члены могут вызываться для rvalue .
operator=
нетoperator()
), но не имеет отношения к вопросу. Пример ничего не делает с результатом присваивания.A()
не вызываетoperator()
, он создает объект типаA
.Если вы действительно хотите, вы можете сделать так, чтобы он не компилировался с C ++ 11:
class A { template <typename T> void operator=(T&&) && = delete; // no op= for rvalues // generate other special members normally A() = default; A(A const&) = default; A(A&&) = default; ~A() = default; // op= only for lvalues A& operator=(A&&) & = default; A& operator=(A const&) & = default; }; int main() { A() = A(); // error return 0; }
( живой пример )
Обратите внимание на символы
&
и&&
(также известные как ref-qualifiers) в конце объявлений различныхoperator=
форм. Это заставляет эти объявления выбираться для lvalues и rvalues соответственно. Однако версия rvalue, выбранная с помощью разрешения перегрузки, приводит к неправильному формату программы, поскольку она удаляется.Однако сгенерированный по умолчанию оператор = не имеет квалификатора ref, то есть его можно вызывать как для lvalue, так и для rvalue; вот почему код в вопросе компилируется, даже если
A()
это rvalue.источник
Компилятор C ++ предоставляет всем классам конструктор по умолчанию, что и происходит с вашим кодом, когда вы говорите A () = A (); он просто вызывает конструктор с безымянным объектом, а функция возвращает ссылку на сконструированный объект (неявно). Это оно...
источник