开发者

C++ make_shared 用法小结

开发者 https://www.devze.com 2025-07-11 11:20 出处:网络 作者: Ring__Rain
目录 ​一、基本用法与语法​⚡ ​二、核心优势​1. ​性能优化(一次内存分配)​​2. ​异常安全​3. ​代码简洁性​ ​三、实际应用场景​1. ​共享对象所有权​2. ​解决循环引用​3. ​高效创建数组(C++20+)​
目录
  • ​一、基本用法与语法​
  • ⚡ ​二、核心优势​
    • 1. ​性能优化(一次内存分配)​​
    • 2. ​异常安全​
    • 3. ​代码简洁性​
  • ​三、实际应用场景​
    • 1. ​共享对象所有权​
    • 2. ​解决循环引用​
    • 3. ​高效创建数组(C++20+)​​
  • ⚠️ ​四、使用限制与注意事项​
    • ️ ​五、最佳实践建议​
      • ​总结​

        以下是C++中std::make_shared的用法详解及核心要点,结合实践场景和代码示例说明:

        ​一、基本用法与语法​

        std::make_shared是C++11引入的模板函数,用于创建并管理std::shared_ptr智能指针,语法如下:

        #include <memory>
        std::shared_ptr<T> ptr = std::make_shared<T>(构造参数...);

        示例​:

        class MyClass {
        public:
            MyClass(int v) : data(v) {}
        private:
            int data;
        };
        QKApBYY 
        int main() {
            auto obj = std::make_shared<MyClass>(42); // 创建对象并初始化
            return 0;
        }
        • 作用​:替代new T(...),自动管理内存生命周期,避免手动delete

        ⚡ ​二、核心优势​

        1. ​性能优化(一次内存分配)​​

        传统方式​(std::shared_ptr<T>(new T)):

        先分配对象内存,再分配控制块(引用计数等),共 ​2次内存分配

        ​**make_shared​:

        将对象和控制块合并为单次内存分配**,减少内存碎片,提升性能(约30%速度提升)

        std::shared_ptr<int> p1(new int(10));   // 2次分配(低效)
        auto p2 = std::make_shared<int>(10);    // 1次分配(高效)

        2. ​异常安全​

        若构造函数抛出异常,make_shared能保证已分配的内存被自动释放,而传统方式可能泄漏:

        // 传统方式:若computePriority()抛出异常,new int的内存泄漏
        process(std::shared_ptr<int>(new int), computePriandroidority());
         
        // maandroidke_shared:异常安全
        process(std::make_shared<int>(), computePriority()); 

        由于make_shared是原子操作,避免了中间状态导致的内存泄漏。

        3. ​代码简洁性​

        • 避免显式new,减少代码冗余。

        ​三、实际应用场景​

        1. ​共享对象所有权​

        多个shared_ptr共享同一对象,引用计数归零时自动释放:

        auto obj = std::make_shared<MyClass>();
        auto obj2 = obj;  // 引用计数+1
        std::cout << obj.use_count(); // 输出2

        对象在objobj2均析构后释放。

        2. ​解决循环引用​

        使用weak_ptr打破循环依赖:

        class B; 
        class A {
        public:
            std::weak_ptr<B> b_ptr; // 弱引用
        };
        class B {
        public:
            std::shared_ptr<A> a_ptr;
        };
         
        int main() {
            auto a = std::make_shared<A>();
            auto b = std::make_shared<B>();
            a->b_ptr = b; // 弱引用,不增加计数
            b->a_ptr = a; // 强引用
            return 0; // 正确释放资源
        }

        若使用shared_ptr互相持有会导致内存泄漏。

        3. ​高效创建数组(C++20+)​​

        // C++20支持make_shared创建数组
        auto arr = std::make_shared<int[]>(5); 
        arr[0] = 42;

        C++11/14需手动构造:std::shared_ptr<int[]>(new int[5])

        ⚠️ ​四、使用限制与注意事项​

        不支持自定义删除器

        make_shared无法指定删除器,需直接使用shared_ptr构造函数

        auto ptr = std::shared_ptr<FILE>(fopen("file.txt", "r"), [](FILE* f){ fclose(f); });

        延迟内存释放问题

        对象内存和控制块合并分配后,若存在weak_ptr,则对象内存需等到所有weak_ptr析构才释放(强引用计数为0时仅析构对象,内存块可能未释放)。

        适用场景​:对内存敏感的系统需谨慎使用。

        python

        私有构造函数限制

        若类构造函数为privateprotected,需通过友元或静态工厂函数间接调用make_sharehttp://www.devze.comd

        ️ ​五、最佳实践建议​

        • ​**优先使用make_shared**​:除非需要自定义删除器或处理私有构造,否则默认选用。
        • 避免循环引用​:成员指针优先用weak_ptr,尤其父子对象互相引用时。
        • 性能敏感场景​:高频创建对象时(如实时系统),make_shared的性能优势更显著。

        ​总结​

        std::make_shared是现代C++内存管理的核心工具:

        • 高效​:单次内存分配提升性能;
        • 安全​:异常安全避免泄漏;
        • 简洁​:代码更清晰易维护。

          在共享所有权、资源自动释放及高性能场景中不可或缺,但需注意其内存释放机制和构造限制。

        到此这篇关于C++ make_shared 用法小结的文章就介绍到这了,更多相关C++ make_shared内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)! 

        0

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        关注公众号