我们使用智能指针来自动运行管理内存,避免对原始指针的使用不当而造成内存泄漏。

 

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

C++里可能出现的内存问题大致有这么几个方面:

1. 缓冲区溢出。

2. 空悬指针 / 野指针。

3. 重复释放。

4. 内存泄漏。

5. 不配对的new[] / delete。

6. 内存碎片。

 

通过正确使用智能指针很容易解决前面5个问题:

 

1. 缓冲区溢出:用std::vector<char> / srd::string 或自己编写Buffer class 来管理缓冲区,自动记住用缓冲区的长度,并通过成员函数而不是裸指针来修改缓冲区。

2. 空悬指针 / 野指针:用shared_ptr / weak_ptr解决。

3. 重复释放:用scoped_ptr,只在对象析构的时候释放一次。   // unique_ptr

4. 内存泄漏:用scoped_ptr, 对象析构的时候自动释放内存。  // unique_ptr

5. 不配对的new[] / delete:把new[] 统统替换为 std::vector。

                                                                                                                                        -------------引用自 陈硕 《Linux多线程服务端编程》

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

下面介绍了这几个智能指针的使用:

一、通过std::shared_ptr这种智能指针访问的对象采用共享所有权来管理其生存期。即内部采用引用计数方式,只有当应用计数为0时,会释放所指资源。

shared_ptr<string> p = make_shared<string>("apple");

我们尽可能使用std::make_shared而避免使用new 来创建对象。(可参考《Effective Modern C++》条款21.)

 

二、std::weak_ptr也是一个应用计数型智能指针,但它不增加对象的引用次数,即弱引用。可以说是std::shared_ptr的一种扩充。weak_ptr不控制对象的生命期,但它知道对象是否还活着(调用lock()) 。

shared_ptr<string> p = make_shared<string>("apple");
weak_ptr<string> wp(p);
shared_ptr<string> sp = wp.lock();          // 如果对象还存在,返回一个shared_ptr,其中包含weak_ptr对象保留的信息。若死了,则返回一个空的shared_ptr。
if (sp) {

}
else {

}

 

三、unique_ptr与shared_ptr不同的是unique_ptr对所管理的资源进行独享,unique_ptr不允许对资源进行拷贝。用来取代std::auto_ptr,可以替换boost库中的scoped_ptr。

unique_ptr<int> p1 = make_unique<int>(5);
unique_ptr<int> p2(p1);    // error
unique_ptr<int> p3 = p1;   // error

我们尽可能使用std::make_unique而避免使用new 来创建对象。(可参考《Effective Modern C++》条款21.)

 

测试代码(以shared_ptr为例智能指针日常使用, 测试环境: VS2017):

#include <iostream>
#include <memory>
#include <string>

using namespace std;

class apple
{
public:
    apple(const string& s = "0") : number(s) { }
    string getString() const { return number; }
private:
    string number;
};

class decorate final
{
public:
    decorate() = delete;  // 不允许单独创建decorate对象
    decorate(const shared_ptr<apple>& rhs) :pta(rhs){  } 
    decorate(const decorate& rhs) : pta(make_shared<apple>(*rhs.pta)) { }
    decorate& operator=(const decorate& rhs);
    
    shared_ptr<apple> getPtr() const { return pta; }
private:
    shared_ptr<apple> pta;
};

decorate& decorate::operator= (const decorate& rhs)
{
    if (this != &rhs)
        pta = rhs.pta;
    return *this;
}


int main()
{
    shared_ptr<apple> pta = make_shared<apple>("yantai-apple");
    decorate myDec(pta);
    cout << myDec.getPtr()->getString() << endl;

    return 0;
}

 

posted on 2018-11-20 17:43  大猫吃西瓜  阅读(385)  评论(0编辑  收藏  举报