Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用shared_ptr.reset或operator=更好吗?_C++_C++11_Shared Ptr - Fatal编程技术网

C++ 使用shared_ptr.reset或operator=更好吗?

C++ 使用shared_ptr.reset或operator=更好吗?,c++,c++11,shared-ptr,C++,C++11,Shared Ptr,我正试图了解C++11的新习惯用法 似乎至少在共享的ptr中,使用newt()和make_-shared()之间有实质性的区别 但是,重置共享指针以指向某个对象的新实例又如何呢。以前,我通常使用reset(newt())member。但是,这不是和不使用make_shared()有同样的问题吗?(即,它不允许make_shared分配对象,因此它被迫将ref计数放置在单独的分配中,而不是与t本身相同的分配中?) 继续使用以下工具是否更好: mysharedptr = make_shared

我正试图了解C++11的新习惯用法

似乎至少在共享的ptr中,使用
newt()
make_-shared()
之间有实质性的区别

但是,重置共享指针以指向某个对象的新实例又如何呢。以前,我通常使用
reset(newt())
member。但是,这不是和不使用make_shared()有同样的问题吗?(即,它不允许make_shared分配对象,因此它被迫将ref计数放置在单独的分配中,而不是与t本身相同的分配中?)

继续使用以下工具是否更好:

   mysharedptr = make_shared<T>(args...);
mysharedptr=make_shared(args…);
还是有更好的办法


而且reset不应该像make_shared那样提供变量转发参数,这样就可以编写mysharedptr.reset(args…)

以下各项之间确实存在实质性差异:

shared_ptr<T> sp(new T());
在这里,编译器可以计算第一个
newt()
表达式,然后计算第二个
newt()
表达式,然后构造相应的
共享对象。但是,如果第二次分配在第一个分配的对象绑定到其
共享\u ptr
之前导致异常,该怎么办?它将被泄露。使用
make_shared()
,这是不可能的:

f(make_shared<T>(), make_shared<T>())
f(make_shared(),make_shared())
由于分配的对象被绑定到
make_shared()
的每个函数调用中相应的
shared_ptr
对象,因此此调用是异常安全的。这是另一个原因,除非你真的知道自己在做什么,否则不应该使用裸
new
。(*)

考虑到您关于
reset()
的评论,您正确地注意到
reset(new T())
将对计数器和对象执行单独的分配,就像在将原始指针作为参数传递时,构造新的
shared_ptr
将执行单独的分配一样。因此,使用
make_shared
的赋值更可取(甚至可以使用
reset(make_shared())
之类的语句)

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

(*)仍有一些情况需要它。例如,C++标准库缺少对应的<代码> MaxION/<代码>函数>代码> UNQuYYPPTR <代码>,因此您必须自己编写一个。另一种情况是,您不希望在单个内存块上分配对象和计数器,因为存在指向该对象的弱指针会阻止整个内存块被释放,即使不再存在指向该对象的拥有指针。

正确,
重置(新T…)
遭受所有共享的问题(新T.);它将导致双重分配,并且是非异常安全的(泄漏的可能性不大,除非
重置
中发生
错误分配

reset
shared_ptr(ptr)等价。swap(*this)
,因此您还可以编写:

make_shared<T>(args...).swap(mysharedptr);
make_shared(args…).swap(mysharedptr);

来自
make_shared
的赋值几乎是等价的,唯一的区别是删除旧
T
和销毁临时
shared_ptr
的相对顺序,这是不可观察的。

我认为很好地注意到异常安全参数足够了(至少对我来说)也就是说,我们甚至不应该再使用
new
,而应该至少使用
make_unique
。这通过设计任何分配来防止任何可能的泄漏。@GManNickG:Yes,
make_unique
是允许使用
new
的例外。顺便说一句,你知道为什么标准库中没有
make_unique
?简单的疏忽。顺便说一句,如果内存不足,您可能仍然不想使用
make_shared
,因为优化将使内存块本身保持活动状态,直到没有更多的弱指针。我想知道make_unique与unique_ptr::reset?在重用分配的t时,是否存在优化?无法重置(假设它是可变的并且使用了完美的转发)简单地重用t的现有内存插槽?@Mordachai,是的,假设
reset
更像容器的
emplace
功能,它可以重用内存,但这个假设不成立,是一个相当大的设计变化。C++11智能指针只负责获取对象的所有权,而不负责为其创建或分配内存。与其销毁、取消分配、分配和构造,也许您只想做
*up=T(args…
?我不确定什么是最好的。但我想现在我要用你交换的std::unique\u ptr和分配的std::shared\u ptr,因为这样可以避免编写
myptr=std::move(make_unique(…)
@Mordachai
move
make_shared
make_unique
的返回值是PR值,因此绑定到右值引用。谢谢。我一定是犯了别的错误,误会了。我现在明白了,简单的赋值可以很好地工作,并且对于多态使用是必需的
p=make_unique()
f(make_shared<T>(), make_shared<T>())
make_shared<T>(args...).swap(mysharedptr);