gpt4 book ai didi

c++ - unique_ptr 的有效性

转载 作者:行者123 更新时间:2023-12-04 04:27:34 27 4
gpt4 key购买 nike

我喜欢 std::unique_ptr我在 c++11 中看到它的那一刻,但我质疑它的有效性很长一段时间。 (有关实时代码的链接,请参见下面的链接):

#include <memory>

std::unique_ptr<int> get();
extern std::unique_ptr<int> val;

void foo()
{
val = get();
}
这给了我关于最后一次 clang 的 16 条指令 -O3 .但更有趣的是,它生成了两个对 delete 的调用。 ,即使永远不会调用第二个。
比我尝试这样做:
void foo()
{
auto ptr = get().release();
val.reset(ptr);
}
突然间只有 11 条指令。然后我更深入地破解了 unique_ptr move ctor。最初它被实现为 reset(__u.release()); .我基本上只是按如下方式重新排序:
auto& ptr =  _M_ptr();
if (ptr)
_M_deleter()(ptr);
ptr = __u.release();
Aaand.... 手动管理版本中的 11 条指令。它略有不同,但似乎还可以。
我保存了我的实验 here .
有人可以指出是我遗漏了什么还是实际上是有意为之?

最佳答案

移动分配的操作顺序必须是:

  • 制作托管源指针的拷贝,并将其在源对象中设为空。
  • 如果目标托管指针不为空,则将其删除。
  • 在目标对象中设置目标托管指针。

  • 请注意,此逻辑愉快地导致自移动分配无操作。
    逻辑必须是这种方式的原因是源可能归目标所有。
    想象:
    struct list { std::unique_ptr<list> next; };
    std::unique_ptr<list> head;
    // ...
    if (head) head = std::move(head->next);
    如果 head->next,这将不会正确运行的托管指针在删除由 head 管理的旧对象之前未被清空.
    在代码中,移动赋值因此只是:
    reset(source.release())
    您的最后一个片段显然无法在删除之前将源清零,因此不是移动分配的可行实现:
    auto& ptr =  _M_ptr();
    if (ptr)
    _M_deleter()(ptr);
    ptr = __u.release();
    这就留下了你为什么要问的问题
    val = get();
    不同于
    auto ptr = get().release();
    val.reset(ptr);
    区别在于隐含的 unique_ptr<int>get() 返回.在第一个版本中,它在 release 之后被销毁。和 reset .在第二个版本中,它在 release 之后被销毁但之前 reset .在这两种情况下,它在被销毁时都为空,并且不需要删除。但是编译器必须无法通过 reset 传播此指针已清零的知识。 .

    关于c++ - unique_ptr 的有效性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67323766/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com