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

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 	


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值