gpt4 book ai didi

c++ - 使用 shared_ptr.reset 还是 operator = 更好?

转载 作者:IT老高 更新时间:2023-10-28 12:36:10 29 4
gpt4 key购买 nike

我正试图围绕 C++11 的新习语展开思考。

似乎至少使用 shared_ptr 与使用 new T() 之间存在实质性区别和 make_shared<T>() .

但是如何重置共享指针以指向某事物的新实例。以前,我通常会使用 reset(new T())成员。但是,这不会遇到与一开始不使用 make_shared() 相同的问题吗? (即它不允许 make_shared 分配对象,因此它被迫将引用计数放在单独的分配中,而不是与 T 本身在同一分配中?)

继续使用会不会更好:

   mysharedptr = make_shared<T>(args...);

或者有没有更好的方法?

并且不应该像 make_shared 那样重置提供参数的可变参数转发,以便可以编写 mysharedptr.reset(args...);?

最佳答案

两者之间确实存在很大差异:

shared_ptr<T> sp(new T());

还有:

shared_ptr<T> sp = make_shared<T>();

第一个版本为 T 执行分配。对象,然后执行单独的分配以创建引用计数器。第二个版本对对象和引用计数器执行一次分配,将它们放置在连续的内存区域中,从而减少内存开销。

此外,在 make_shared<> 的情况下,某些实现能够执行进一步的空间优化。 (请参阅 MS 实现完成的“我们知道你住在哪里”优化)。

然而,这并不是 make_shared<> 的唯一原因。存在。基于显式 new T() 的版本在某些情况下不是异常安全的,尤其是在调用接受 shared_ptr 的函数时.

void f(shared_ptr<T> sp1, shared_ptr<T> sp2);

...

f(shared_ptr<T>(new T()), shared_ptr<T>(new T()))

在这里,编译器可以计算第一个 new T()表达式,然后计算第二个 new T()表达式,则构造对应的shared_ptr<>对象。但是,如果在第一个分配的对象绑定(bind)到它的 shared_ptr<> 之前,第二次分配导致异常怎么办? ?它会被泄露。与 make_shared<>() ,这是不可能的:

f(make_shared<T>(), make_shared<T>())

因为分配的对象绑定(bind)到相应的shared_ptr<>每个函数内的对象调用 make_shared<>() ,这个调用是异常安全的。这也是为什么裸new 的另一个原因。除非您真的知道自己在做什么,否则永远不要使用。 (*)

考虑到您对 reset() 的评论,您观察到 reset(new T()) 是对的将为计数器和对象执行单独的分配,就像构造一个新的 shared_ptr<>当原始指针作为参数传递时,将执行单独的分配。因此,使用 make_shared<> 的赋值更可取(甚至是 reset(make_shared<T>()) 之类的声明)。

是否reset()应该支持可变参数列表,这可能更像是一种开放式讨论,StackOverflow 不适合。

(*) 有一些情况仍然需要它。例如,C++ 标准库缺少相应的 make_unique<> 的事实。 unique_ptr 的函数,所以你必须自己写一个。另一种情况是当您不希望将对象和计数器分配在单个内存块上时,因为指向对象的弱指针的存在会阻止 整个 block 被释放,即使没有存在更多指向该对象的拥有指针。

关于c++ - 使用 shared_ptr.reset 还是 operator = 更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14836691/

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