【问题标题】:Does std::make_shared() use custom allocators?std::make_shared() 是否使用自定义分配器?
【发布时间】:2012-12-29 09:35:43
【问题描述】:

考虑this code

#include <memory>
#include <iostream>


class SomeClass {
public:
    SomeClass() {
        std::cout << "SomeClass()" << std::endl;
    }

    ~SomeClass() {
        std::cout << "~SomeClass()" << std::endl;
    }

    void* operator new(std::size_t size) {
        std::cout << "Custom new" << std::endl;
        return ::operator new(size);
    }

    void operator delete(void* ptr, std::size_t size) {
        std::cout << "Custom delete" << std::endl;
        ::operator delete(ptr);
    }
};



int main() {
    std::shared_ptr<SomeClass> ptr1(new SomeClass);
    std::cout << std::endl << "Another one..." << std::endl << std::endl;
    std::shared_ptr<SomeClass> ptr2(std::make_shared<SomeClass>());
    std::cout << std::endl << "Done!" << std::endl << std::endl;
}

这是它的输出:

Custom new
SomeClass()

Another one...

SomeClass()

Done!

~SomeClass()
~SomeClass()
Custom delete

显然,std::make_shared() 没有调用 new 运算符——它使用的是自定义分配器。这是std::make_shared() 的标准行为吗?

【问题讨论】:

    标签: c++ c++11 shared-ptr make-shared


    【解决方案1】:

    是的,这是标准行为。从标准(§20.7.2.2.6 shared_ptr 创建):

    效果:分配适合类型 T 对象的内存,并通过放置新表达式 ::new (pv) T(std::forward&lt;Args&gt;(args)...). 在该内存中构造一个对象

    这允许make_shared 在一次分配中为共享指针本身(“控制块”)的对象和数据结构分配存储空间,以提高效率。

    如果您想控制存储分配,可以使用std::allocate_shared

    【讨论】:

    • std::allocate_shared(const A&amp;, Args&amp;&amp;...) 也值得一提。第一个参数是调用A::allocate on 的分配器。
    【解决方案2】:

    为了扩展 Mat 的正确答案,make_shared 通常通过分配一个包含 shared_ptr 引用计数和未初始化字节缓冲区的对象来实现:

    template<typename T>
      struct shared_count_inplace
      {
        long m_count;
        long weak_count;
        typename std::aligned_storage<sizeof(T)>::type m_storage;
        // ...
      };
    

    这是将在堆上分配的类型,而不是您的类型,因此您的类型的new 不会被调用。然后您的类型将使用位置new 的位置(void*)&amp;m_storage 构造。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-07
      • 2014-02-01
      • 1970-01-01
      • 2020-03-27
      • 2014-01-28
      • 1970-01-01
      相关资源
      最近更新 更多