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

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

未完待续…

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

时间: 2024-09-28 01:34:45

【C++】智能指针(Smart Pointer)的相关文章

智能指针(smart pointer)(2):unique_ptr

Unique pointer: Manages the storage of a pointer, providing a limited garbage-collection facility, with little to no overhead over built-in pointers (depending on the deleter used). These objects have the ability of taking ownership of a pointer: onc

智能指针(smart pointer)(1):auto_ptr

智能指针解决了资源生存期管理的问题(尤其是动态分配的对象).智能指针有各种不同的风格.多数都有一种共同的关键特性:自动资源管理.这种特性可能以不同的方式出现:如动态分配对象的生存期控制,和获取及释放资源 (文件, 网络连接).这里主要讨论第一种情况,它们保存指向动态分配对象的指针,并在正确的时候删除这些对象. 何时我们需要智能指针? 有三种典型的情况适合使用智能指针: ? 资源所有权的共享 ? 要写异常安全的代码时 ? 避免常见的错误,如资源泄漏 共享所有权,当多个对象需要同时使用第三个对象的情

(转)Delphi2009初体验 - 语言篇 - 智能指针(Smart Pointer)的实现

快速导航 一. 回顾历史二. 智能指针简介三. Delphi中的interface四. Delphi中智能指针的实现五. interface + 泛型 = 强类型的智能指针!六. 智能指针与集合七. 注意事项八. 总结 本随笔所有源代码打包下载 一.回顾历史 在c++中,对象可以创建在栈里,也可以创建在堆里.如: class CTestClass{public: CTestClass() { printf("Create"); } void DoPrint() {} ~CTestCla

C++深度探索系列:智能指针(Smart Pointer) [一]

阿里妹导读:以深度学习为代表的人工智能在图像.语音和NLP领域带来了突破性的进展,在信息检索和个性化领域近几年也有不少公开文献,比如wide& deep实现了深度模型和浅层模型的结合,dssm用于计算语义相关性,deepfm增加了特征组合的能力,deep CF用深度学习实现协同过滤,rnn recommender 采用行为序列预估实现个性化推荐等. 工业级的信息检索或个性化系统是一个复杂的系统工程,深度学习的工业级应用需要具备三个条件:强大的系统计算能力,优秀的模型设计能力和合适的应用场景.今天

智能指针 与 oc中的指针

智能指针 与 oc中的指针 智能指针的原理及实现 当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝:另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享. 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针. 每次创建类的新对象时,初始化指针并将引用计数置为1:当对象作为另一对象的副

C++中智能指针的设计和使用

转载请标明出处,原文地址:http://blog.csdn.net/hackbuteer1/article/details/7561235      智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露.它的一种通用实现技术是 使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针.每次创建类的新对象时,初始化指针并将引用计数置为

智能指针的实现--使用引用计数实现以及原理

一.智能指针 在C++语言编程时,当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝:另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享. 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针. 每次创建类的新对象时,初始化指针并将引用计数置为1:当对象作为另一对象的副本而创建时,拷贝

【C++】智能指针类和OpenCV的Ptr模板类

智能指针类 引用计数 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一对象.引用计数为0时,删除对象. 其基本使用规则是: 每次创建类的新对象时,初始化指针并将引用计数置为1.当对象作为另一对象的副本而创建时,复制构造函数复制指针并增加与之相应的引用计数的值.对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数的值(如果引用计数减至0,则删除对

【C++】C++问题——类模板分离编译、函数对象、智能指针

C++类模板的分离编译 过去很多类模板都是整个类连同实现都放在一个头文件里,像STL库就是遵循这样的策略来实现类模板的.现在的标准正试图矫正这种局面. 在实现中又许多函数模板.这意味着每个函数都必须包含模板声明,并且在使用作用域操作符的时候,类的名称必须通过模板变量来实例化. 比如一个operator=的代码: template <typename Object> const MemoryCell <Object> & MemoryCell<Object>::o