简体   繁体   English

移动 std::unique_ptr 的构造函数/赋值:memory 重新分配?

[英]move constructor/assignment of std::unique_ptr: memory reallocation?

In using move constructor/assignment of std::unique_ptr , can one assume that the underlying object is not reallocated in memory, such that a raw pointer to it remains valid?在使用std::unique_ptr的移动构造函数/赋值时,可以假设底层 object 没有在 memory 中重新分配,这样指向它的原始指针仍然有效吗?

Consider the following program:考虑以下程序:

#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;
}

Here w is constructed with the default move constructor of A , which calls the move constructor of std::unique_ptr .这里w是使用A的默认移动构造函数构造的,它调用std::unique_ptr的移动构造函数。

It appears by the output that the underlying allocated int is not really moved in memory, so the default move constructor correctly initialized wp as identical to vp . output 显示底层分配的int并未真正在 memory 中移动,因此默认移动构造函数正确地将wp初始化为与vp相同。 Trying with other types for T gives analog result.尝试使用其他类型的T会产生模拟结果。

Can one assume that the move constructor of std::unique_ptr does not really move the object in memory, so that in the above program the default move constructor is correct?是否可以假设std::unique_ptr的移动构造函数并没有真正移动 memory 中的 object,所以在上述程序中默认的移动构造函数是正确的? Is that specified by the language?那是由语言指定的吗?

Or to avoid a dangling pointer must one add a move constructor explicitly like the following?或者为了避免悬空指针必须显式添加一个移动构造函数,如下所示?

A(A<T>&& other) : data{std::move(other.data)}, p{data.get()} { }

From the standard, [unique.ptr.single.ctor]/20从标准来看, [unique.ptr.single.ctor]/20

 unique_ptr(unique_ptr&& u) noexcept;

Postconditions: get() yields the value u.get() yielded before the construction.后置条件:get() 产生构造前产生的值 u.get()。 u.get() == nullptr. u.get() == nullptr。

No memory allocation happens in move construction;移动构造中没有发生 memory 分配; after A<int> w{std::move(v)};A<int> w{std::move(v)}; , w.data.get() (and wp ) would be the same as v.data.get() before, ie vp . w.data.get() (和wp )将与之前的v.data.get()相同,即vp

And the move constructor of std::unique_ptr is marked as noexcept , which also implies that no memory allocation here.并且std::unique_ptr的移动构造函数被标记为noexcept ,这也意味着这里没有 memory 分配。

IMO even the implicitly-generated move constructor works fine here, adding a user-defined one is better, especially you can set the raw pointer p to nullptr in the moved object (for consistency). IMO 即使隐式生成的移动构造函数在这里也能正常工作,添加一个用户定义的更好,特别是您可以在移动的 object 中将原始指针p设置为nullptr (为了保持一致性)。

A(A<T>&& other) : data{std::move(other.data)}, p{data.get()} { other.p = nullptr; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM