A () = A () - чому він компілюється?


85
class A {};

int main() {
 A() = A();
 return 0; 
}

Чому цей код компілюється? Чи не повинно бути помилок, які ліворуч від оператора присвоювання слід розміщувати lvalue? Чи є значення A () l? версія g ++ 4.7

Відповіді:


88

Для вбудованих типів ви мали б рацію: вбудований оператор присвоєння вимагає змінної lvalue зліва.

Однак тут використовується не вбудований оператор, а перевантаження, яке неявно оголошено класом. Це функція-член, еквівалентна

A().operator=(A());

а функції-члени можна викликати на rvalues .


7
це не ініціалізація копії?
зоряний пил

13
@Named: Ні, це призначення не ініціалізація.
Майк Сеймур

1
@ paul23: Це правда (припускаючи, що ти маєш на увазі operator=ні operator()), але не має багато спільного з питанням. Приклад нічого не робить із результатом призначення.
Майк Сеймур

3
@ paul23 A()не викликає operator(), він створює об'єкт типу A.
інтержой

3
Це не може бути ініціалізацією, оскільки немає декларації.
Кос

32

Якщо ви дійсно хочете, ви можете зробити так, щоб він не компілювався з 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; 
}

( живий приклад )

Зверніть увагу на &та &&(також відомі кваліфікатори) у кінці декларацій різних operator=форм. Це змушує ці декларації бути обраними для lvalues ​​та rvalues ​​відповідно. Однак версія rvalue, вибрана за допомогою дозволу на перевантаження, спричиняє неправильну форму програми, оскільки вона видаляється.

Типово згенерований оператор =, однак, не має жодного кваліфікатора ref, тобто його можна викликати як для lvalues, так і для rvalues; тому код у питанні компілюється, хоча A()це і є значенням.


1

Компілятор C ++ надає всім класам конструктор за замовчуванням, ось що відбувається стосовно вашого коду, коли ви говорите A () = A (); він просто викликає конструктор з безіменним об'єктом, а функція повертає посилання на побудований об'єкт (неявний). Це воно...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.