您的位置:首页 > 产品设计 > UI/UE

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

2017-05-18 17:02 495 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: