enable_shared_from_this和make_shared是否提供相同的优化

Dmi*_*roh 10 c++ shared-ptr make-shared

据我所知,make_shared<T>(...)可以提供一些内存分配优化(它可以在与T类实例相同的内存块中分配引用计数器).

enable_shared_from_this提供相同的优化吗?所以:

class T : std::enable_shared_from_this<T> {};
...
auto t = std::shared_ptr<T>(new T);
Run Code Online (Sandbox Code Playgroud)

是相同的:

class T {};
...
auto t = std::make_shared<T>();
Run Code Online (Sandbox Code Playgroud)

如果不考虑sizeof(T).

Jon*_*ely 9

enable_shared_from_this提供相同的优化吗?所以:

不可以.从标准中的措辞可以看出,enable_shared_from_this<T>有一个weak_ptr<T>数据成员.这会weak_ptr<T>向类添加一个类,该类具有指向包含引用计数的控制块的指针.它不直接包含引用计数.包含引用计数的控制块仍存在于对象外部.

包含引用计数的控制块必须比对象寿命长,以便weak_ptr用于引用该对象的其他对象仍然可以访问控制块,以检查它是否已过期.

如果控制块在对象内部,则在对象被销毁时将被销毁,并且悬挂不可能weak_ptr安全地确定对象是否已经过期.理论上,控制块的内存可以保持分配并仍然可以使用并更新引用计数,即使它们所属的对象被破坏了,但这看起来很丑陋(这意味着对象不会被破坏delete,它需要一个显式的析构函数调用和显式operator delete调用来释放内存).

如果拥有shared_ptr 是使用自定义删除器或自定义分配器创建的,则也无法使用嵌入式控制块,因为这些对象的大小不会提前知道.在这种情况下,除了嵌入在enable_shared_from_this<T>基类中的外部控制块之外,还需要分配一个外部控制块,从而浪费更多空间.

  • 是的,使用`make_shared`,在删除最后一个弱引用之前,内存不会被释放.但是没关系,因为`make_shared`控制分配+构造和销毁+解除分配,所以可以正确地完成所有操作.使用`shared_ptr <X>(new X)`对象应该用`delete`来销毁,但是这会阻止控制块超过对象(因为一旦析构函数运行就会释放内存). (2认同)