Итак, если у меня есть класс и я объявляю в нем оператор присваивания копии, очевидно, мне нужно какое-то особое поведение при копировании. Я ожидаю, что язык попытается помочь мне, неявно удалив конструктор копирования, пока я не верну его явно, чтобы избежать непреднамеренного другого поведения при выполнении type instance = type()
, а не already_existing_instance = type()
.
В любом случае рекомендуется явно объявлять конструктор копирования и оператор присваивания при попытке объявить один из них именно потому, что C++ не удаляет другой и вызывает у вас головную боль.
Примером того, где я нахожу это раздражающим, является удаление оператора присваивания копии. Если я хочу быстро сделать класс некопируемым, я ожидаю, что удаление оператора присваивания копирования поможет, но я также должен явно удалить конструктор копирования.
Мой вопрос: почему компилятор это делает? Кто подумал, что это хорошая идея? Все, что он делает, это создает ненужное препятствие для программиста, или я что-то упускаю?
P.S. Это поведение не проявляется, когда вы делаете то же самое с конструкторами перемещения/операторами присваивания, зачем в этом случае делать различие между копированием и перемещением?
@ ALX23z Можете ли вы уточнить, что вы имеете в виду, когда говорите, что «нельзя выполнять указанные операции по умолчанию»? В моих примерах не используется ключевое слово по умолчанию, вы имеете в виду что-то другое?
Возможно, однажды timsong-cpp.github.io/cppwp/n4868/…
По умолчанию я имею в виду запись = default
. Поэтому, когда это невозможно сделать, если, скажем, по какой-то причине ctor копирования по умолчанию был отключен, вам придется написать полную реализацию вручную, даже если вам нужен вариант по умолчанию.
Например. Clang 15 с -Wextra
, дано
struct A
{
A() {}
A(const A &) {}
};
int main()
{
A a, b;
a = b;
}
плюется
<source>:4:5: warning: definition of implicit copy assignment operator for 'A' is deprecated because it has a user-provided copy constructor [-Wdeprecated-copy-with-user-provided-copy]
A(const A &) {}
^
<source>:10:7: note: in implicit copy assignment operator for 'A' first required here
a = b;
^
Сходным образом,
struct A
{
A() {}
A &operator=(const A &) {return *this;}
};
int main()
{
A a, b(a);
}
дает
<source>:4:8: warning: definition of implicit copy constructor for 'A' is deprecated because it has a user-provided copy assignment operator [-Wdeprecated-copy-with-user-provided-copy]
A &operator=(const A &) {return *this;}
^
<source>:9:10: note: in implicit copy constructor for 'A' first required here
A a, b(a);
^
Абсолютно фантастично. Просто чтобы убедиться, что я не ошибаюсь, устаревание означает, что они удалят его в будущем, верно?
@NikTedig Надеюсь, да.
@NikTedig - устаревший означает, что он может быть удален в будущем. Это не обещание; это предупреждение.
... или больше угрозы.
Компиляторы, как правило, получают предупреждение, когда есть пользовательский копирайтер, но не копируют присваивание наоборот. Это наследование от pre-C++11, когда нельзя было выполнить указанные операции по умолчанию.