c++ - move std::unique_ptr的构造函数/分配:内存重新分配?

标签 c++ c++11 unique-ptr move-semantics

在使用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的默认move构造函数构造,该构造函数调用std::unique_ptr的move构造函数。

输出显示,底层分配的int并未真正在内存中移动,因此默认的move构造函数正确地将w.p初始化为与v.p相同。
尝试使用其他类型的T可获得模拟结果。

可以假设std::unique_ptr的move构造函数并未真正在内存中移动对象,因此在上述程序中,默认的move构造函数正确吗?
是语言指定的吗?

还是要避免悬空的指针,必须像下面这样显式地添加一个move构造函数?
A(A<T>&& other) : data{std::move(other.data)}, p{data.get()} { }

最佳答案

从标准[unique.ptr.single.ctor]/20

unique_ptr(unique_ptr&& u) noexcept;

Postconditions: get() yields the value u.get() yielded before the construction. u.get() == nullptr.


移动构造中不会发生内存分配;在A<int> w{std::move(v)};之后,w.data.get()(和w.p)将与之前的v.data.get()相同,即v.p
并将std::unique_ptr的move构造函数标记为noexcept,这也意味着此处没有内存分配。
IMO甚至隐式生成的move构造函数在这里都可以正常工作,添加一个用户定义的更好,尤其是可以在移动对象中将原始指针p设置为nullptr(出于一致性)。
A(A<T>&& other) : data{std::move(other.data)}, p{data.get()} { other.p = nullptr; }

关于c++ - move std::unique_ptr的构造函数/分配:内存重新分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61334937/

相关文章:

c++11 - 当析构函数是私有(private)的时,我应该如何在 c++11 中使用唯一指针?

c++ - 使用 unique_ptrs 的基本前向列表

c++ - QT - 切换 .ui 的问题

c++ - 使 GCC 5.1.0 作为非 root 用户与 CUDA 7.5 一起工作

C++11 右值引用寻址

c++ - 如何使用 boost::function 参数将 lambda 传递给重写方法?

c++ - 列表初始值设定项

c++ - 如何在 STL 堆栈中保存用户定义的类型?

c++ - 我应该如何定义带有默认参数的 std::function 变量?

c++ - 我应该分配还是重置一个 unique_ptr?