有一个例子表明以这种方式使用RAII:
class File_ptr{
//...
File* p;
int* i;
public:
File_ptr(const char* n, const char* s){
i=new int[100];
p=fopen(n,a); // imagine fopen might throws
}
~File_ptr(){fclose(p);}
}
void use_file(const char* fn){
File_ptr(fn,"r");
}
Run Code Online (Sandbox Code Playgroud)
是安全的.但我的问题是:如果抛出异常,p=fopen(n,a);那么分配给的内存i不会被返回.这是正确的假设,RAII然后告诉你每次你想要X安全,那么所有获得的资源X必须在堆栈上分配?如果X.a正在创建,那么资源a也必须放在堆栈上?再一次,我的意思是,如果有一些资源放在堆上,如何用RAII处理它?如果它不是我的类,即
Exc*_*ius 11
RAII的重点是不要将任何资源(如int-array)分配给悬空指针.相反,使用std::vector或指定数组指针std::unique_ptr.这样,资源将在异常发生时被销毁.
不,你不必使用STL,但是为了利用RAII,最低的基础资源(比如堆分配的数组)也必须使用RAII创建,最简单的方法是使用STL而不是而不是写自己的智能指针或向量.
将此视为您不想使用的智力练习std::vector,您需要将您的班级分开,以便他们承担单一职责。这是我的“整数数组”类。它的职责是管理整数数组的内存。
class IntArray {
public:
IntArray() : ptr_(new int[100]) {}
~IntArray() { delete[] ptr_; }
IntArray(const IntArray&) = delete; // making copyable == exercise for reader
IntArray& operator=(const IntArray&) = delete;
// TODO: accessor?
private:
int* ptr_;
};
Run Code Online (Sandbox Code Playgroud)
这是我的文件处理类。它的职责是管理一个FILE*.
class FileHandle {
public:
FileHandle(const char* name, const char* mode)
: fp_(fopen(name, mode))
{
if (fp_ == 0)
throw std::runtime_error("Failed to open file");
}
~FileHandle() {
fclose(fp_); // squelch errors
}
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
// TODO: accessor?
private:
FILE* fp_;
};
Run Code Online (Sandbox Code Playgroud)
请注意,我将构造错误转换为异常;fp_作为一个有效的文件指针是我希望维护的一个不变量,因此如果我无法设置这个不变量,我将中止构造。
现在,使File_ptr异常安全变得很容易,并且该类不需要复杂的资源管理。
class File_ptr {
private:
FileHandle p;
IntArray i;
public:
File_ptr(const char* n, const char* s)
: p(n, s)
, i()
{}
};
Run Code Online (Sandbox Code Playgroud)
请注意,缺少任何用户声明的析构函数、复制赋值运算符或复制构造函数。我可以交换成员的顺序,在任何一种情况下,哪个构造函数抛出并不重要。
| 归档时间: |
|
| 查看次数: |
752 次 |
| 最近记录: |