2014-10-31 2 views
1

Это может быть тривиальный вопрос, однако я не нашел удовлетворительного ответа и не могу понять, что происходит.Оператор перегрузки =

Предположим, у вас есть следующий код:

#include <iostream> 

class Foo 
{ 
public: 
    void operator=(int) 
    { 
     std::cout << "calling Foo::operator=(int)" << std::endl; 
    } 
}; 

int main() 
{ 
    Foo a, b; 
    a = 10; // it works, of course, no questions here 
    a = b; // why does this work? 
} 

Поскольку я перегружен operator= в Foo, я бы ожидать линии a = b внутри main() плюнуть ошибку компилятора (то есть, a.operator=(b) не должен составлять, как есть нет неявного преобразования от b до int, причем последний является типом ввода Foo::operator=(int)). Почему задание a = b бесшумно работает, и что именно происходит? Является ли компилятор генерирующим «default» operator=(const Foo&) даже в том случае, когда я перегружал его?

ответ

1

Да, компилятор генерирует значение по умолчанию, тривиальное Foo& operator=(const Foo&). Там только четыре случая, в которых оператор копирующего присваивания неявно не будет генерироваться:

  • вы явно сказали это не (например, Foo& operator=(const Foo&) = delete)
  • вы объявили его самостоятельно, принимая Foo (или Foo& или const Foo&)
  • ваш класс имеет нетривиально-назначаемый элемент (например, unique_ptr<T>)
  • вашего класса имеет определенный оператор присваивания движения или конструктор (спасибо Брайан)

Обновление Вот некоторые части, относящиеся к стандарту.

12.8.18:

Если определение класса не явно объявить оператор присваивания копии, один объявлен неявно. Если определение класса объявляет конструктор перемещения или переносит оператор присваивания, оператор назначения неявно объявленной копии определяется как удаленный; в противном случае она определяется как дефолте

Хорошо, но вы сделал объявить оператор присваивания копии, не так ли? Или вы? Что именно является оператора копирующего присваивания:

12.8.17:

Пользователя объявленного оператора копирующего присваивания X::operator= не является статической функция, не являющийся членом шаблон класса X ровно с одним параметром от X, X&, const X&, volatile X& или const volatile X&. 121 [Примечание: Перегруженный оператор присваивания должен быть объявлен как имеющий только один параметр; см. 13.5.3. - примечание к концу] [Примечание: для класса может быть объявлено более одного вида оператора присваивания копии.- конец примечание] [Примечание: Если класс X имеет только оператор присваивания копии с параметром типа X&, выражение типа const X не может быть отнесено к объекту типа X

Так нет. Функция, которую вы объявили как Foo::operator=(int), будучи оператором присваивания, не является оператором присваивания . Следовательно, он не удовлетворяет условию предыдущего абзаца, неявно объявляя его.

Все другие условия определяются в 12.8.23:

дефолт Оператор присваивания копирования/перемещения для класса X определяется как удаляется, если X имеет:

  • член вариант с нетривиальным соответствующим оператором присваивания и X является объединенным классом, или
  • нестатический элемент данных типа const не-класса (или его массив) или
  • нестатический элемент данных ссылочного типа или
  • нестатический элемент данных класса M (или его массив), который нельзя скопировать/перемещать, поскольку разрешение перегрузки (13.3) применительно к соответствующему присвоению M оператор приводит к двусмысленности или функции, которая была удалена или недоступна от оператора присваивания по умолчанию, или
  • прямой или виртуальный базовый класс B, который нельзя скопировать/переместить, поскольку значение перегрузки (13.3), так как применяется к B соответствующий оператор присваивания, приводит к двусмысленности или функции, которая удалена или недоступна от оператора присваивания по умолчанию, или
  • для оператора присваивания переадресации, нестатического элемента данных или прямого базового класса с типом не имеет оператора присваивания переадресации и не является тривиально-копируемым или любым прямым или косвенным виртуальным базовым классом .
+0

Спасибо, вам кажется, что вы знаете стандарт :) У вас есть сек. номер? – vsoftco

+0

Неявно объявленный оператор присваивания копии также будет определен как удаленный, если есть явно объявленный механизм перемещения или оператор назначения перемещения. – Brian

+0

@Brian, спасибо, что я знал, был просто любопытством к оператору присваивания. Кажется немного странным, что нельзя указать «явный» для перегруженных операторов. Это может быть полезно, особенно когда вы имеете дело с объектами прокси. – vsoftco

Смежные вопросы