设为首页 加入收藏

TOP

浅谈c++资源管理以及对[STL]智能指针auto_ptr源码分析,左值与右值(一)
2016-04-28 13:28:51 】 浏览:756
Tags:浅谈 资源管理 以及 STL 智能 指针 auto_ptr 源码 分析 左值与

1. 知识引入

C++编程中,动态分配的内存在使用完毕之后一般都要delete(释放),否则就会造成内存泄漏,导致不必要的后果。虽然大多数初学者都会有这样的意识,但是有些却不以为意。我曾问我的同学关于动态内存的分配与释放,他的回答是:”只要保证new和delete成对出现就行了。如果在构造函数中new(动态分配内存),那么在析构函数中delete(释放)就可以避免内存泄漏了!”

事实果真如此么?

实例一:

(当子函数中动态分配的内存只在子函数中使用而不返回指向该动态内存的指针时,子函数中动态分配的内存即使不释放也不会造成内存泄漏,因为在销毁栈的同时,会自动释放该内存。因此,我用main函数举例)

int main(void) {
    int *a = new int(35);
    if (*a != 50) return 0;
    delete a;
    return 0;
}

在这种情况下,new和delete虽然成对出现,但是仍出现了内存泄漏的情况。因此,成对出现并不能保证不会发生内存泄漏。

实例二:

class A {
 public:
     A(): a(NULL) {}
     A(int a) {
        this->a = new int(a);
     }
     ~A() {
        if (a != NULL) delete a;
     }
     A operator =(A src) {
        this->a = new int(src.a);
     }
 private:
    int *a; 
};

int main(void) {
    A num(10);
    A num1(15);
    num = num1;
    return 0;
}

在这种情况下,构造函数new(动态分配)一段内存,析构函数delete(释放)这段内存。看似在对象建立时调用构造完成内存分配,在对象销毁时调用析构释放内存,一切都很正常不会造成内存泄漏,但是问题就出在了num = num1;上,即是重载“=”出现问题导致内存泄漏。因为在赋值之前,num中的a已经指向堆中一段内存,而且是访问该内存的唯一方式。一旦直接赋值,会导致这块内存无法被访问,因此导致了内存泄漏。

由此看来,内存泄漏的情况很容易出现,那么有没有方法可以避免这种情况发生呢?

这时,我们可以设计一个类似于资源管理的类,来实现对指针指向的动态内存的管理。这个类的精髓在于,成员变量用于指向动态内存,析构函数用于释放该变量指向的动态内存。即:

template 
   
     class manage { public: manage(T *p) : pArr(p) {} ~manage() { if (pArr != NULL) delete pArr; } T* get() { return pArr; } private: T *pArr; };
   

这个资源管理类没有设置无参数的构造函数的原因是:该类需满足:RAII机制

RAII机制:RAII,也称为“资源获取就是初始化”,是c++等编程语言常用的管理资源、避免内存泄露的方法。
RAII的做法:使用一个对象,在其构造时获取资源,在对象生命期控制对资源的访问使之始终保持有效,最后在对象析构的时候释放资源。

那么什么是资源获取就是初始化呢?那就是new(动态分配内存)后直接将地址作为参数传入给资源管理类的对象(调用对象的构造函数)。

manage
   
     instance(new int[10]);
   

new(动态分配)的int[10]的地址就直接用于初始化instance对象,这就是资源获取就是初始化。

如果我们再往这个类中加入成员方法,这就构成了一个完整的资源管理类,也就是智能指针auto_ptr。

According to cplusplus.com, auto_ptr is in

class template std::auto_ptr

template 
   
     class auto_ptr;
   

Automatic Pointer [deprecated]
Note: This class template is deprecated as of C++11. unique_ptr is a new facility with a similar functionality, but with improved security (no fake copy assignments), added features (deleters) and support for arrays. See unique_ptr for additional information.

This class template provides a limited garbage collection facility for pointers, by allowing pointers to have the elements they point to automatically destroyed when the auto_ptr object is itself destroyed.

auto_ptr objects have the peculiarity of taking ownership of the pointers assigned to them: An auto_ptr object that has ownership over one element is in charge of destroying the element it points to and to deallocate the memory allocated to it when itself is destroyed. The destructor does this by calling operator delete automatically.

Therefore, no two auto_ptr objects should own the same element, since both would try to destruct them at some point. When an assignment operation takes place between two auto_ptr objects, ownership is transferred, which means that the object losing ownership is set to no longer point to the element (it is set to the null pointer).

Template parameters
X: The type of the managed object, aliased as member type element_type.

不过有一点十分重要,auto_ptr的对象在构造时获得动态内存的ownership(所有权),且在析构时释放这段内存,更重要的是,在调用复制构造函数时是实现ownership(所有权)的转移而不是深拷贝,拥有这段动态内存的对象只能有一个

auto_ptr 源码如下:

template
   
     class auto_ptr { private: T*ap; public: //constructor & destructor-----------------------------------(1) explicit auto_ptr(T*ptr=0)throw():ap(ptr) {} ~auto_ptr()throw() { delete ap; } //Copy & assignment------
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇序列分割 题解&代码(C++) 下一篇数据结构与算法 - 图的邻接表表示..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目