Поведение по умолчанию:
- ctor по умолчанию (
T()
): вызывает базы def. ctors и члены по умолчанию ctors.
- Копировать ctor (
T(const T&)
): вызывает копирование базы. ctors и участники копируют ctors.
- Move ctor (
T(T&&)
): вызывает движение баз. ctors и участники перемещают ctors.
- Назначить (
T& operator=(const T&)
): вызывает назначение баз. и члены назначают.
- Передача (
T& operator=(T&&)
): вызывает передачу базы и передачу участников.
- Деструктор (
~T()
): вызывает деструктор члена и базовый деструктор (обратный порядок).
Для встроенных типов (int и т.д.)
- Ctor по умолчанию: установлен в 0, если вызывается явно
- Копировать ctor: побитовое копирование
- Переместить ctor: побитовое копировать (без изменений в исходном коде)
- Назначить: побитовое копирование
- Перенос: побитовое копирование
- Деструктор: ничего не делает.
Поскольку указатели также являются встроенными типами, это относится к int*
(а не к тому, на что он указывает).
Теперь, если вы ничего не объявляете, ваш класс T
будет просто содержать int*, которому не принадлежит указанный int, поэтому копия T будет просто содержать указатель на тот же int. Это такое же результирующее поведение, как и в C++03. Реализованное по умолчанию перемещение для встроенных типов — это копирование. Поскольку классы перемещаются по элементам (и зависит от того, какие члены: просто копии для встроенных)
Если вам нужно изменить это поведение, вы должны сделать это последовательно: например, если вы хотите «владеть» тем, на что указываете, вам нужно
- ctor по умолчанию инициализируется
nullptr
: это определяет «пустое состояние», на которое мы можем ссылаться позже
- ctor-создатель, инициализирующий заданный указатель
- копировщик, инициализирующий копию указанного (это реальное изменение)
- dtor, который удаляет указанный
- назначение, которое удаляет указанное и получает новую копию указанного
.
T::T() :_param() {}
T::T(int* s) :_param(s) {}
T(const T& s) :_param(s._param? new int(*s._param): nullptr) {}
~T() { delete _param; } // will do nothing if _param is nullptr
Давайте пока не будем определять присваивание, а сконцентрируемся на перемещении: если вы не объявляете его, так как вы объявили копию, она будет удалена: это делает объект T всегда копируемым, даже если временно (то же поведение, что и С++ 03)
Но если исходный объект временный, мы можем создать пустой пункт назначения и поменять их местами:
T::T(T&& s) :T() { std::swap(_param, s._param); }
Это то, что называется перемещением.
Теперь присваивание: перед C++11 T& operator=(const T& s)
должно свериться с самоприсваиванием, сделать место назначения пустым и получить копию указанного:
T& operator=(const T& s)
{
if(this == &s) return *this; // we can shortcut
int* p = new int(s._param); //get the copy ...
delete _param; //.. and if succeeded (no exception while copying) ...
_param = p; // ... delete the old and keep the copy
return *this;
}
С C++11 мы можем использовать передачу параметров для создания копии, таким образом давая
T& operator=(T s) //note the signature
{ std::swap(_param, s._param); return *this; }
Обратите внимание, что это работает и в C++98, но проходная копия не будет оптимизирована при проходном перемещении, если s
является временным. Это делает такую реализацию невыгодной в C++98 и C++03, но очень удобной в C++11.
Также обратите внимание, что нет необходимости специализировать std::swap
для T: std::swap(a,b);
будет работать, будучи реализованным как три хода (не копирование).
Практика реализации функции обмена происходит для случая, когда T имеет много членов, и обмен требуется как при перемещении, так и при назначении. Но это может быть и обычная частная функция-член.
person
Emilio Garavaglia
schedule
27.06.2014
If you don't use assignment/copy constructor, what does *... = delete* do precisly, what's the difference with declaring them private?
stackoverflow.com/questions/ 18847957/ - person 101010   schedule 27.06.2014= delete
). Но я бы сказал, что в типичных случаях некопируемые неподвижные классы встречаются не так часто. C++ — это не Java, мы обычно предпочитаем хранить наши объекты по значению. - person Angew is no longer proud of SO   schedule 27.06.2014