c++11 stl 学习之 shared_ptr

shared_ptr

智能指针 shared_ptr 的声明初始化方式

由于指针指针使用explicit参数 必须显示声明初始化

shared_ptr<string> pNico = new string("nico"); // ERROR

shared_ptr<string> pNico{new string("nico")}; // OK

也可以使用make_shared()

shared_ptr<string> pNico = make_shared<string>("nico");

shared_ptr<string> pJutta = make_shared<string>("jutta");

智能指针一旦声明

就不能再次分配 除非使用reset()

shared_ptr<string> pNico4;

pNico4 = new string("nico");

//ERROR: no assignment for ordinary pointers

pNico4.reset(new string("nico")); // OK

shared_ptr的使用方式与实际指针使用类似 基本没什么区别

示例 sharedPtrTest1()

//=======================================

对于shared_ptr中的参数 可以指定 删除器 Deleter

示例 sharedPtrTest2()

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <fstream> //for ofstream
#include <cstdio> //for remove()

using namespace std;


void sharedPtrTest1()
{
        shared_ptr<string> pNico(new string("nico"));
        shared_ptr<string> pJutta(new string("jutta"));

        (*pNico)[0] = 'N';
        pJutta->replace(0, 1, "J");

        vector<shared_ptr<string>> whoMadeCoffee;
        whoMadeCoffee.push_back(pJutta);
        whoMadeCoffee.push_back(pJutta);
        whoMadeCoffee.push_back(pNico);
        whoMadeCoffee.push_back(pJutta);
        whoMadeCoffee.push_back(pNico);

        for (auto ptr : whoMadeCoffee) {
                cout << *ptr << " ";
        }
        cout << endl;
        // overwrite a name again
        *pNico = "Nicolai";
        // print all elements again
        for (auto ptr : whoMadeCoffee) {
                cout << *ptr << " ";
        }
        cout << endl;
        // print some internal data
        cout << "use_count: " << whoMadeCoffee[0].use_count() << endl;
}


class FileDeleter
{
private:
        std::string filename;
public:
        FileDeleter(const std::string& fn)
                : filename(fn) {
        }
        void operator () (std::ofstream* fp) {
                fp->close(); //close.file
                std::remove(filename.c_str()); //delete file
                cout << "delete file finish" << endl;
        }
};

void sharedPtrTest2()
{
        shared_ptr<std::ofstream> fp(new std::ofstream("tmpfile.txt"),
                FileDeleter("tmpfile.txt"));
}




int _tmain(int argc, _TCHAR* argv[])
{
        sharedPtrTest1();
        sharedPtrTest2();

        return 0;
}

  

shared_ptr的误用

下面是错误示例

int* p = new int;

shared_ptr<int> sp1(p);

shared_ptr<int> sp2(p);

这将产生错误 对于int指针有两个智能指针的内存管理器对其进行管理

sp1 sp2 都对其关联的资源进行释放

正确的代码如下:

shared_ptr<int> sp1(new int);

shared_ptr<int> sp2(sp1);

还有一种隐蔽的情况 也会发生这种错误:

比如在Person 中增加一个函数setParentsAndTheirKids()

void setParentsAndTheirKids(shared_ptr<Person> m = nullptr,

shared_ptr<Person> f = nullptr)

{

mother = m;

father = f;

if (m != nullptr){

m->kids.push_back(shared_ptr<Person>(this));

}

if (f != nullptr){

f->kids.push_back(shared_ptr<Person>(thid));

}

}

int _tmain(int argc, _TCHAR* argv[])

{

string name("nico");

shared_ptr<Person> mom(new Person(name + "'s mom"));

shared_ptr<Person> dad(new Person(name + "'s dad"));

shared_ptr<Person> kid(new Person(name + "name"));

kid->setParentsAndTheirKids(mom,dad);

return 0;

}

但是如果在自己的类中使用包含this的shared_ptr指针 会增加引用计数

导致无法释放

所以引进enable_shared_from_this类

#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;


class Person : public std::enable_shared_from_this<Person> {
public:
        string name;
        shared_ptr<Person> mother;
        shared_ptr<Person> father;
        //vector<shared_ptr<Person>> kids;
        vector<weak_ptr<Person>> kids;

        Person(const string& n,
                shared_ptr<Person> m = nullptr,
                shared_ptr<Person> f = nullptr)
                :name(n), mother(m), father(f){
        };

        ~Person(){
                cout << "delete " << name << endl;
        }

        //====================================
        void setParentsAndTheirKids(shared_ptr<Person> m = nullptr,
                shared_ptr<Person> f = nullptr)
        {
                mother = m;
                father = f;
                if (m != nullptr){
                        m->kids.push_back(shared_ptr<Person>(shared_from_this()));
                }
                if (f != nullptr){
                        f->kids.push_back(shared_ptr<Person>(shared_from_this()));
                }
        }
};





int _tmain(int argc, _TCHAR* argv[])
{
        string name("nico");
        shared_ptr<Person> mom(new Person(name + "'s mom"));
        shared_ptr<Person> dad(new Person(name + "'s dad"));
        shared_ptr<Person> kid(new Person(name + "name"));

        kid->setParentsAndTheirKids(mom,dad);

        return 0;
}