本文介绍了是更好地使用shared_ptr.reset或operator =?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我试着用C ++ 11的新成语包装。 似乎至少有shared_ptr,使用 new T()和 make_shared< T>()。 $ b b 但是什么重置一个共享指针指向一个新的实例的东西。以前,我通常使用 reset(new T())成员。然而,这不会遇到同样的问题,因为不使用make_shared()在第一个地方? (即它不允许make_shared分配对象,因此它被强制将引用计数放置在单独的分配中,而不是与T本身在相同的分配中)。 这是更好的前进使用: mysharedptr = make_shared< T>(args ...); 还是有更好的方法吗? 解决方案不应该重置提供变量的参数的转发作为make_shared的,所以可以写mysharedptr.reset(args ...) / div> 确实有很大的区别: shared_ptr< T> sp(new T()); 和: code> 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& ... f(shared_ptr< T>(new T()),shared_ptr< T>(new T())) 这里,编译器可以评估第一个 new T()第二个 new T()表达式,然后构造相应的 shared_ptr<> 对象。但是如果第二个分配在第一个分配的对象绑定到它的 shared_ptr<> 之前引起异常怎么办?它会泄漏。使用 make_shared<>()不可能: 由于分配的对象是绑定的,因此f(make_shared< T>(),make_shared< T>()) 到 make_shared<>()的每个函数调用内的相应 shared_ptr< / code> -安全。这是为什么裸体 new 永远不要使用,除非你真的知道你在做什么的另一个原因。 (*) 考虑你对 reset()的说法,你是正确的观察 reset(new T())将对计数器和对象执行单独的分配,就像构造一个新的 shared_ptr<< / code&将在将原始指针作为参数传递时执行单独的分配。因此,优选使用 make_shared<> 的赋值(或甚至诸如 reset(make_shared< T>()))。 是否 reset()应该支持一个可变参数列表,一种开放讨论,对StackOverflow不是一个很好的适合。 (*)有一些情况下仍然需要它。例如,C ++标准库缺少 unique_ptr 的相应 make_unique<> 函数,我必须自己写一个。另一种情况是当你不希望将对象和计数器分配在单个内存块上时,因为存在指向该对象的弱指针将阻止整个块被释放,即使没有更多拥有对象的指针存在。 I'm trying to wrap my head around the new idioms for C++11.It seems that with shared_ptr at least, there is a substantive difference between using new T() and make_shared<T>().But what of resetting a shared pointer to point to a new instance of something. Previously, I would typically use reset(new T()) member. However, doesn't this suffer from the same problem as not using make_shared() in the first place? (i.e. it doesn't allow make_shared to allocate the object, therefore it is forced to place the ref count in a separate allocation instead of in the same allocation as the T itself?)Is it simply better going forward to use: mysharedptr = make_shared<T>(args...);Or is there a better way?And shouldn't reset offer variadic forwarding of arguments as make_shared does, so that one could write mysharedptr.reset(args...);? 解决方案 There is indeed a substantial difference between:shared_ptr<T> sp(new T());And:shared_ptr<T> sp = make_shared<T>();The first version performs an allocation for the T object, then performs a separate allocation to create the reference counter. The second version performs one single allocation for both the object and the reference counter, placing them in a contiguous region of memory, resulting in less memory overhead.Also, some implementations are able to perform further space optimizations in the case of make_shared<> (see the "We Know Where You Live" optimization done by MS's implementation).However, that is not the only reason why make_shared<> exists. The version based on explicit new T() is not exception-safe in some situations, especially when invoking a function that accepts a shared_ptr.void f(shared_ptr<T> sp1, shared_ptr<T> sp2);...f(shared_ptr<T>(new T()), shared_ptr<T>(new T()))Here, the compiler could evaluate the first new T() expression, then evaluate the second new T() expression, then construct the corresponding shared_ptr<> objects. But what if the second allocation causes an exception before the first allocated object is bound to its shared_ptr<>? It will be leaked. With make_shared<>(), this is not possible:f(make_shared<T>(), make_shared<T>())Because allocated objects are bound to the respective shared_ptr<> objects inside each function call to make_shared<>(), this call is exception-safe. This is yet another reason why naked new should never be used unless you really know what you are doing. (*)Considering your remark about reset(), you are right in observing that reset(new T()) will perform separate allocations for the counter and the object, just as the construction of a new shared_ptr<> will perform a separate allocation when a raw pointer is passed as an argument. Therefore, an assignment using make_shared<> is preferable (or even a statement such as reset(make_shared<T>())).Whether or not reset() should support a variadic argument list, this is probably more of a kind of open discussion for which StackOverflow is not a good fit.(*) There are a few situations that still require it. For instance, the fact that the C++ Standard Library lacks a corresponding make_unique<> function for unique_ptr, so you'll have to write one yourself. Another situation is when you do not want the object and the counter to be allocated on a single memory block, because the presence of weak pointers to the object will prevent the entire block from being deallocated, even though no more owning pointers to the object exist. 这篇关于是更好地使用shared_ptr.reset或operator =?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
10-16 22:34