Mis*_*tyD 6 c++ pointers shared-ptr make-shared
我发现了这篇文章,其中一个答案是@kerek SB说的
Run Code Online (Sandbox Code Playgroud)std::shared_ptr<Object> p1 = std::make_shared<Object>("foo"); std::shared_ptr<Object> p2(new Object("foo"));在你的代码中,第二个变量只是一个裸指针,而不是一个共享指针.
现在就肉了.make_shared(实际上)更有效,因为它在一个动态分配中将引用控制块与实际对象一起分配.相比之下,采用裸对象指针的shared_ptr的构造函数必须为引用计数分配另一个动态变量.权衡是make_shared(或其表兄allocate_shared)不允许您指定自定义删除器,因为分配是由分配器执行的.
(这不会影响对象本身的构造.从Object的角度来看,两个版本之间没有区别.更有效的是共享指针本身,而不是托管对象.)
现在我对这篇文章有两个问题,如果有人能澄清一下,我会很感激
为什么第二个不是共享指针?这不会增加引用计数
make_shared如何只进行一次内存分配,而new将两次内存分配,从而使make_shared更有效率?
对此有点澄清将不胜感激.
在那个问题中,"第二个变量"引用了这一行:
auto ptr_res2(new Object("new")); // this creates an Object*
Run Code Online (Sandbox Code Playgroud)
不是这个:
std::shared_ptr<Object> p2(new Object("foo")); // this creates a shared_ptr<Object>
Run Code Online (Sandbox Code Playgroud)
为什么make_shared一次分配更有效的最佳解释是比较图像.这是std_shared_ptr<Object>(new Object)看起来像:

该shared_ptr有Widget*,但由于它们被分别分配给这不是在同一个内存块作为裁判计数器.所述Widget*被传递,和ref计数块内部分配,这就是为什么Widget是在一个单独的存储空间.
另一方面,这是一个分配的样子:

(我偷了Herb Sutter的两张照片).我们还需要Widget和裁判计数模块,而是整个内存块被抓住在一个单一的呼叫new/ malloc,只是足够的尺寸,所以Widget和ref计数模块结束了连续在内存中.
被称为第二个变量的代码实际上是这样的(取自OP的代码):
auto ptr_res2(new Object("new"));
Run Code Online (Sandbox Code Playgroud)
这不会创建a std::shared_ptr,而是创建一个指向 的指针Object。
当使用裸指针创建std::shared_ptr使用其构造函数时,必须将指针传递给已分配的内存(例如使用分配的内存new)。这意味着在创建对象本身时已经分配了对象的内存std::shared_ptr。需要std::shared_ptr为其自身的工作分配内存,例如引用计数器。因此,有两种分配:一种是使用new传递给 的 ctor 的分配std::shared_ptr,另一种是构造std::shared_ptr自身时所需的分配。
Object* ptr = new Object{"Foo"}; // Allocation 1 (object).
std::shared_ptr<Object> p1{ptr}; // Allocation 2 (internal counters).
Run Code Online (Sandbox Code Playgroud)
当您向辅助函数std::make_shared传递构造对象所需的参数(而不是指向对象本身的指针)时,辅助函数仅使用 1 次分配。然后可以分配一次内存来保存对象和引用计数器。std::make_shared
auto p2 = std::make_shared<Object>{"Foo"} // Allocation 1 (object & counter).
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
3050 次 |
| 最近记录: |