shared_ptr简单应用

shared_ptr 是C++共享指针,往往应用在动态分配内存的场景下。相较于new操作符的优势在于shared_ptr共享指针可以自动进行动态内存释放,而new必须与delete配合使用,否则会造成内存泄露。

一个好的建议是:坚持只使用智能指针,就可以避免忘记delete造成的内存泄露,避免同一块内存被释放两次的问题。对于一块内存,只有在没有任何智能指针指向它的情况下才会自动释放它。

shared_ptr还可以作为class的成员,以使该class的对象能够共享数据。下面的代码进行了一下简单的实践。

#include 
#include 
#include 
#include 

using namespace std;
class intBlob
{
     
    friend ostream &printBlob(ostream &os, intBlob &blob);
public:
    explicit intBlob(initializer_list<int> il) : data_(make_shared<vector<int>>(il))
    {
     
        std::cout << "列表初始化构造函数" << std::endl;
    }
    intBlob() : data_(make_shared<vector<int>>())
    {
     
        std::cout << "默认构造函数" << std::endl;
    }
    intBlob(const intBlob &blob) : data_(blob.data_)
    {
     
        std::cout << "拷贝构造函数" << std::endl;
    }

    intBlob& operator=(const intBlob& b2)
    {
     
        data_ = b2.data_;
        return *this;
    }

    ~intBlob()
    {
     
        std::cout<<"析构函数"<<std::endl;
    }
    void push_back(int d);

    void printUseCount()
    {
     
        std::cout << "shared_ptr used count: " << data_.use_count() << endl;
    }

private:
    shared_ptr<vector<int>> data_;
};

void intBlob::push_back(int d)
{
     
    data_->push_back(d);
}

ostream &printBlob(ostream &os, intBlob &blob)
{
     
    os << "blob data size:" << blob.data_->size() << std::endl;
    for (auto &d : *(blob.data_))
    {
     
        os << d << " ";
    }
    os << std::endl;
}

int main()
{
     
    intBlob B1{
     0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    
    {
     
        intBlob B2(B1);
        printBlob(cout, B1);//这里说明友元函数可以访问class的私有成员
        printBlob(cout, B2);
        B1.printUseCount();
        B2.printUseCount();
        B2.push_back(10);
    }//出该作用域前B2对象会被析构,shared_ptr内部的计数器自动减1,因此会看到下面的B1.printUseCount()变成了1
    B1.printUseCount();
    
    printBlob(cout,B1);//B2对data所指的vector进行了push_back,虽然这里B2已经被析构了,但是B1所用的vector也有了10
    //可以看出B1和B2确实共享了数据
    intBlob B3;

    printBlob(cout, B3);
    return 0;
}

运行结果

列表初始化构造函数
拷贝构造函数
blob data size:10
0 1 2 3 4 5 6 7 8 9 
blob data size:10
0 1 2 3 4 5 6 7 8 9 
shared_ptr used count: 2
shared_ptr used count: 2
析构函数
shared_ptr used count: 1
blob data size:11
0 1 2 3 4 5 6 7 8 9 10 
默认构造函数
blob data size:0

析构函数
析构函数

shared_ptr可以使用普通的内置指针进行初始化,但是这样做是有风险的。如下:

int *p = new int(50);
shared_ptr<int> p1_shared(p);
shared_ptr<int> p2_shared(p);
shared_ptr<int> p3_shared(p1_shared);
std::cout<<p1_shared.use_count()<<" "<<p2_shared.use_count()<<" "<<p3_shared.use_count()<<std::endl;

打印结果如下:

2 1 2

实际上p1_shared、p2_shared和p3_shared都指向同一个int对象,所以use_count都为3才是正确的。但是如果用一个内置指针单独去初始化不同的shared_ptr,则智能指针内部的计数器是感受不到的。因此在释放内存的时候就可能产生悬空指针。p3_shared因为是用p1_shared初始化的,所以它和p1_shared的use_count打印为2,也就是它们都不知道还有一个p2_shared也指向了同一个内存。

因此不要混用普通指针和智能指针。

你可能感兴趣的:(C++,primer,11学习)