Я пытаюсь создать программу, которая реализует взаимодействие между «копировать и менять» идиому и и move control operations
, поэтому я написал этот код:
class PInt
{
public:
PInt(int = 0);
PInt(const PInt&);
PInt(PInt&&) noexcept;
PInt& operator=(PInt);
~PInt();
int* getPtr()const;
private:
int* ptr;
friend void swap(PInt&, PInt&);
};
PInt::PInt(int x) :
ptr(new int(x))
{
std::cout << "ctor\n";
}
PInt::PInt(const PInt& rhs) :
ptr(new int(rhs.ptr ? *rhs.ptr : 0))
{
std::cout << "copy-ctor\n";
}
PInt::PInt(PInt&& rhs) noexcept :
ptr(rhs.ptr)
{
std::cout << "move-ctor\n";
rhs.ptr = nullptr; // putting rhs in a valid state
}
PInt& PInt::operator=(PInt rhs)
{
std::cout << "copy-assignment operator\n";
swap(*this, rhs);
return *this;
}
PInt::~PInt()
{
std::cout << "dtor\n";
delete ptr;
}
void swap(PInt& lhs, PInt& rhs)
{
std::cout << "swap(PInt&, PInt&\n";
using std::swap;
swap(lhs.ptr, rhs.ptr);
}
PInt gen_PInt(int x)
{
return {x};
}
int main()
{
PInt pi1(1), pi2(2);
//pi1 = pi2; // 1
//pi1 = PInt{}; // 2
//pi1 = std::move(pi2); // 3
pi1 = std::move(PInt{}); // 4
}
Все есть Хорошо для меня, поэтому я думаю, что в 1
copy-ctor вызывается оператором copy-asignment для инициализации его параметра (он принимает значение), а затем использует swap. в "2" я присваиваю из r-значения, таким образом, я думаю, что компилятор применяет некоторую оптимизацию "Copy-elision"; создание непосредственно объекта в операторе копирования-копирования.
В чем я не уверен, так это 3 и 4. Итак, вот результат 3 и 4:
строка без комментариев 3:
ctor
ctor
move - ctor
copy - assignment operator
swap(PInt&, PInt &
dtor
dtor
dtor
строка без комментариев 4:
ctor
ctor
ctor
move - ctor
copy - assignment operator
swap(PInt&, PInt &
dtor
dtor
dtor
dtor
- Почему 3 и 4 используют
std::move
, но для получает n дополнительный конструктор с именем?
** Что эффективно: определение оператора копирования / перемещения-присваивания, принимаемого по значению или двух отдельных версий: назначение копирования и назначение перемещения? Поскольку одна версия каждый раз вызывала ее, она вызывает (дополнительный вызов) copy-ctor или move-ctor для инициализации своего параметра?