RAII(Resource Acquisition Is Initialization:资源获取即初始化)

来源:互联网 发布:淘宝网店服装模特招聘 编辑:程序博客网 时间:2024/06/05 09:10
1.裸指针,操作不当导致,空悬指针(指针所指向的资源已经被释放,但是指针未置空),内存泄漏,重复释放
2.栈展开的过程中不会自动释放
3.应用RAII技巧,将裸指针换为智能指针(是一个类),将指针转为对象,对象的析构函数在生命周期结束的时候是确定被调用的
4.RAII(Resource Acquisition Is Initialization:资源获取即初始化)。一个对象可拥有资源。在对象的构造函数中执行资源的获取(指针的初始化),在析构函数中释放。
5.资源:内存,文件句柄,套接字,互斥量
NodePtr.h#ifndef _NODEPTR_H_#define _NODEPTR_H_class Node {public:Node() {std::cout << "Node()"<< std::endl;}virtual ~Node() {std::cout << "~Node()"<< std::endl;}virtual void Calc() {std::cout << "Node::Calc()"<< std::endl;}};class ChildNode: public Node {public:ChildNode() {std::cout << "ChildNode()"<< std::endl;}virtual ~ChildNode() override {std::cout << "~ChildNode()"<< std::endl;}virtual void Calc() {std::cout << "ChildNode::Calc()"<< std::endl;}};template<typename T>class NodePtr {private:T* ptr_;public:explicit NodePtr(T* ptr=0):ptr_(ptr) {}NodePtr(NodePtr<T>& ptr):ptr_(ptr.Release()) {}//不同类之间,比如继承体系template<typename U>NodePtr(NodePtr<U>& ptr):ptr_(ptr.Release()) {}NodePtr& operator=(NodePtr<T>& ptr) {Reset(ptr.Release());return *this;}//不同类之间,比如继承体系template<typename V>NodePtr& operator=(NodePtr<V>& ptr) {Reset(ptr.Release());return *this;}template<typename _Other>operator NodePtr<_Other>() {return (NodePtr<_Other>(*this));}~NodePtr() {delete ptr_;ptr_ = NULL;}T* operator->() {//return ptr_;return &(operator*());}T& operator*() {return *ptr_;}T* Get() const {return ptr_;}T* Release() {T* tmp = this->ptr_;ptr_ = NULL;return tmp;}void Reset(T* ptr) {if(ptr_ != ptr) {delete ptr_;}ptr_ = ptr;}};#endif // _NODEPTR_H_main.cpp#include <iostream>#include <memory>#include <vector>using namespace std;#include "DebugNew.h"#include "NodePtr.h"int main(void) {int* p = new int;//cout << p << endl;delete p;int* p2 = new int[5];delete []p2;//Node* node = new Node;  // 裸指针//NodePtr<Node> ptr(new Node);//ptr->Calc();//(*ptr).Calc();//NodePtr<Node> ptr2(ptr);//NodePtr<Node> ptr3;////ptr3 = ptr2;//////ptr2->Calc();//ptr3->Calc();NodePtr<Node> ptr4(new ChildNode);//ptr4->Calc();NodePtr<Node> ptr5(new ChildNode);//ptr5->Calc();ptr4 = ptr5;if(NULL == ptr5.Get()) {cout << "ptr5 is NULL " << endl;}//ptr4->Calc();std::auto_ptr<Node> node(new Node);vector<std::auto_ptr<Node>> v;//v.push_back(v);/* 1.auto_ptr不能作为STL容器元素2.STL容器要求存放在容器中的元素是值语义3.auto_ptr的拷贝构造或者赋值操作 会改变 有操作数, 因为有操作数的所有权要发生转移 */return 0;}/*合理地使用智能指针,就能够保证编码不内存泄漏C++代码std::vector<Node*> childs_;void AppendChild() {childs_.push_back(node.release());}指针所有权释放了vector 保存的是指针本身,并没有保存指针所指向的内存vector 不负责指针所指向内存管理vector 内部至少要分配4个字节的内存,才够存放现代操作系统都支持虚拟内存要插入的裸指针还没插入到vector, 概率低vector析构的时候,是否会释放所指向的内存呢,他只负责指针变量本身std::auto<Node> node(new Node);vector<std::autor<Node> > v;v.push_back(node);STL容器要求存放在容器中的元素能够被拷贝,也就是要求类型是值语义对象auto_ptr就是值语义  实际上是对象语义 转化为值语义解决方法:可以采用其他类型的智能指针,shared_ptr, scoped_ptr           boost库,ptr_container, ptr_vector指针容器*///new(__FILE__, __LINE__) int