При использовании конструктора перемещения / присваивания std::unique_ptr
можно ли предположить, что базовый объект не перераспределен в памяти, так что необработанный указатель на него остается действительным?
Рассмотрим следующую программу:
#include <memory>
#include <utility>
#include <iomanip>
#include <iostream>
template <class T>
struct A {
std::unique_ptr<T> data = nullptr;
T *p;
template <class... U>
A(U&&... x) : data{std::make_unique<T>(std::forward<U>(x)...)}, p{data.get()} { }
};
int main()
{
A<int> v{2};
std::cout << std::hex << v.p << std::endl;
A<int> w{std::move(v)};
std::cout << w.p << std::endl;
}
Здесь w
создается с конструктором перемещения по умолчанию A
, который вызывает конструктор перемещения std::unique_ptr
.
Выходные данные показывают, что базовый выделенный int
действительно не перемещен в памяти, поэтому конструктор перемещения по умолчанию правильно инициализировал w.p
как идентичный v.p
. Попытка с другими типами для T
дает аналоговый результат.
Можно ли предположить, что конструктор перемещения std::unique_ptr
действительно не перемещает объект в памяти, так что в приведенной выше программе конструктор перемещения по умолчанию является правильным ? Это определяется языком?
Или чтобы избежать висящего указателя, нужно явно добавить конструктор перемещения, как показано ниже:
A(A<T>&& other) : data{std::move(other.data)}, p{data.get()} { }