码迷,mamicode.com
首页 > 编程语言 > 详细

【C++】智能指针(Smart Pointer)

时间:2015-07-22 13:12:25      阅读:218      评论:0      收藏:0      [点我收藏+]

标签:智能指针   unique-ptr   shared-ptr   weak-ptr   auto-ptr   

1. 传统指针存在的问题

传统指针存在诸多的问题,比如指针所指向的对象的生命周期问题,挂起引用(dangling references),以及内存泄露(memory leaks).
如下是一个传统指针的使用过程

void Foo() {
    int *iPtr = new int[5];
    // manipulate the memory block
    // ...
    // ...
    // ...
    delete[] iPtr;
}

以上代码将正常运行且内存将被合理释放,但是使用指针常会发生一些意想不到的事情,比如访问一个非法的内存单元,除0操作,以及根据一些判断条件处理的返回return 语句。

2. 什么是智能指针(Smart Pointer)

智能指针是RAII(Resource Acquisition is initialization)用来动态的分配内存。它提供了普通指针的所有接口外加少数异常处理。在构造阶段,它将分配内存,而在非其作用域内将自动释放所占有的内存。
在C++98中,使用 auto_ptr来解决上述问题。

2.1 auto_ptr

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

class Test {
public:
    Test(int a = 0) : m_a(a) {}
    ~Test() {
        cout << "Calling destructor" << endl;
    }

public:
    int m_a;
};

int main()
{
    auto_ptr<Test> p(new Test(5));
    cout << p->m_a << endl;
    return 0;
}

输出结果:
技术分享
上述代码将智能的释放相关的内存。

#include <iostream>
#include <memory>

using namespace std;

class Test {
public:
    Test(int a = 0) : m_a(a) {}
    ~Test() {
        cout << "Calling destructor" << endl;
    }

public:
    int m_a;
};

void Fun()
{
    int a = 0, b = 5, c;
    if(a == 0) {
        throw "Invalid divisor";
    }
    c = b / a;
    return;
}

int main()
{
    try {
        auto_ptr<Test> p(new Test(5));
        Fun();
        cout << p->m_a << endl;
    }
    catch(...) {
        cout << "Something has gone wrong" << endl;
    }

    return 0;
}

在上述代码中,即使异常抛出,指针照样被正常释放。这是因为当异常抛出时,栈松绑(stack unwinding)。 当所有属于try block的本地对象被销毁时,指针p不在作用域中而被释放。

问题1.

至少从目前来说auto_ptr是智能的。但是它有一个非常本质的缺点:auto_ptr会传递它本身的ownership当其被赋值给另一个auto_ptr对象。正如下述程序所示,一个auto_ptr对象传递给函数Fun()中的auto_ptr对象时,其ownership,或者说是smartness将不再返回给原auto_ptr所指向的p。

#include <iostream>
#include <memory>

using namespace std;

class Test {
public:
    Test(int a = 0) : m_a(a) {}
    ~Test() {
        cout << "Calling destructor" << endl;
    }

public:
    int m_a;
};

void Fun(auto_ptr<Test> p1)
{
    cout << p1->m_a << endl;
    cout << "Fun() end" << endl;
}

int main()
{
    auto_ptr<Test> p(new Test(5));
    Fun(p);
    cout << p->m_a << endl;

    return 0;
}

运行结果:
技术分享
以上程序将crash因为存在野指针auto_ptr。上述代码奔溃的主要原因是,原先的p占有对其自身分配内存的管理权。然而通过Fun()函数将其管理权转给p1,此时因为p1的smartness,在其结束时将释放其所指向的内存块。而此时原先的p将再拥有任何内存,而导致在访问时出现了空指针,野指针的引用问题。

问题2.

auto_ptr不能使用于数组对象。 这里的意思是不能使用于操作符new[]

int main()
{
    auto_ptr<Test> p(new Test[5]);
    return 0;
}

上述代码将runtime error。因为对于auto_ptr而言,其调用的是delete而非delete []

问题3.

auto_ptr不能使用于一些标准的容器库。比如vectorlistmap等等。

C++11提出了新型的智能指针,并且都赋予了其相应的意图。

2.2 shared_ptr

未完待续…

版权声明:本文为博主原创文章,未经博主允许不得转载。

【C++】智能指针(Smart Pointer)

标签:智能指针   unique-ptr   shared-ptr   weak-ptr   auto-ptr   

原文地址:http://blog.csdn.net/zone_programming/article/details/47000647

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!