C++ make_shared使用

C++内存分四大块

  1. 全局 主函数运行前使用,初始化

  2. 静态 变量第一次使用前,初始化
    以上两块内存都会在程序结束后自动释放

  3. 堆区 由程序员管理,C++管理方法有new delete等关键字

  4. 栈区 由编译器管理,存放程序的局部变量和参数

因此我们需要关注堆区的内存管理。内存管理经常会碰到忘记释放造成的内存泄露。
在C++中引入了智能指针,有shared_ptr,unique_ptr和weak_ptr。

shared_ptr

工作中shared_ptr用得比较多,今天做个总结
使用智能指针,需要引入头文件,shared_ptr顾名思义是多个指针指向一块内存。
被管理对象有一个引用计数,这个计数记录在每个指针上,几个shared_ptr指向它,这个数字就是几,当没有任何shared_ptr指向它时,引用计数为0,这时,自动释放对象。
其功能在于当所有指针都释放(或是不再指向对象)的时候,自动释放对象

即,当一个所有指向这块内存的指针生命周期结束时,这块内存会被释放
智能指针的唯一作用,就是自动delete对象,即C++11的新特性,内存管理机制。
智能指针既然会自动delete对象,我们就不能再去手动delete对象了,否则,也会发生多次释放的问题

例:

#include <iostream>
#include <memory>
 
class Test {
public:
    // 无参构造函数
    Test();
    // 有参数的构造函数
    explicit Test(int a);
    // 析构函数
    ~Test();
};
 
Test::Test() {
    std::cout << "无参构造函数" << std::endl;
}
 
Test::Test(int a) {
    std::cout << "有参构造函数,a=" << a << std::endl;
}
 
Test::~Test() {
    std::cout << "析构函数" << std::endl;
}
 
int main(int argc, const char * argv[]) {
    auto p1 = new Test; // 划分堆空间
    std::shared_ptr<Test> sp(p1); // 创建智能指针
    std::cout << sp.use_count() << std::endl; // 打印引用计数
    {
        std::shared_ptr<Test> sp2(sp); // 创建另一个智能指针
        std::cout << sp.use_count() << std::endl; // 打印引用计数
    } // sp2生命周期结束,sp引用计数减1
    std::cout << sp.use_count() << std::endl; // 打印引用计数
    
    return 0;


执行结果

无参构造函数
1
2
1
析构函数

make_shared的引入

一个坑


int main(int argc, const char * argv[]) {
    auto p1 = new Test; // 划分堆空间
    std::shared_ptr<Test> sp(p1); // 创建智能指针
    std::shared_ptr<Test> sp2(p1); // 创建另一个智能指针
    
    return 0;
    }

这段程序会抛出异常 double free detected

new关键字返回的是对应的指针类型。

此处用了两个智能指针管理同一块内存,因为sp 和sp2不知道彼此的存在,所以也会重复释放。

同一个对象只能用同一套内存管理体系,如果它已经有智能指针了,那么再创建智能指针时,需要通过原来已有的指针创建,而不能重复用原始空间来创建。

STL库提供了make_shared函数,其原型为

template <typename T, typename ...Args>
std::shared_ptr<T> std::make_shared(Args && ...args)

官方鼓励用make_shared函数来创建对象,而不要手动去new,这样就可以防止我们去使用原始指针创建多个引用计数体系。

int main(int argc, const char * argv[]) {
    auto sp = std::make_shared<int>(); // 分配堆空间,创建智能指针
    auto sp2 = sp; // 创建另一个智能指针
    
    return 0;
}

参考
https://blog.csdn.net/fl2011sx/article/details/103941346

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值