如何实现RAII +延迟初始化
How to implement RAII + lazy initialization?
是否有可能在c++中实现两者的设计- RAII,确保资源被安全释放,以及-延迟初始化,即资源只有在真正使用时才会被获取。
我的想法是,只是实现作为一个延迟初始化,而在真正的资源获取,使用RAII。
行业惯例如何?
是的,有可能。只要使用std::optional
(c++ 17或从Boost)或unique_ptr
/shared_ptr
。
(意见)optional
在可读性上有很大的优势——你不能再清楚了,这个值可能没有被初始化。
要显示资源被正确释放:首先让我们从急切初始化(live)开始:
ofstream file("test.txt");
file << "no flushn";
ifstream inFile("test.txt");
string line;
getline(inFile, line);
cout << line << endl;
这个,不为我打印任何东西¹。让我们将写入移到单独的作用域(live):
{
ofstream file("test.txt");
file << "no flushn";
}
ifstream inFile("test.txt");
string line;
getline(inFile, line);
cout << line << endl;
应该打印no flush
,因为ofstream
保证在销毁时将close()
文件。(除非test.txt
同时被访问)
现在是Boost。可选的惰性init (live):
{
boost::optional<std::ofstream> file;
file = ofstream("test.txt");
file.get() << "no flushn";
}
ifstream inFile("test.txt");
string line;
getline(inFile, line);
cout << line << endl;
资源与常规ofstream
同时释放。
¹文件访问不能保证被缓冲,但它提供了一个很好的示例,也可用于在线编译器。
通常的做法是尽可能避免延迟初始化。
如果存在延迟初始化方案,则没有什么可以阻止对象的调用者(或用户)在对象实际初始化之前执行依赖于被初始化的对象的操作。这会导致混乱。
为了处理这个问题,对象(或类)实现需要跟踪对象是否实际初始化。这使得类的实现更加复杂——如果任何成员函数忘记检查对象是否初始化,或者任何成员函数将对象置于无效状态,混乱就会随之而来。如果对象(或类)不这样做,则类更难使用,因为使用该类的代码的任何错误都会导致问题。
相反,更常用的技术是(1)构造函数建立一个不变量(2)成员函数假定维护该不变量,(3)析构函数清理。
换句话说,构造函数初始化对象,成员函数确保对象保持在合理状态。当调用成员函数....时,允许假设对象处于有效状态所以不需要检查。只要所有成员函数在返回时确保对象仍然处于有效状态,就没有问题。
唯一的例外是析构函数,它导致对象不再存在。换句话说,在销毁一个对象(调用它的析构函数)之后,不应该再使用该对象的任何成员。
对于调用者来说,这很简单——在获得创建对象所需的信息之前,不要创建对象。换句话说,不是
SomeObject object;
// gather data needed to initialise object
// Danger, danger: it is possible to mistakenly use object as if it is initialised here
object.initialise(needed_data);
// do other things with object
//object ceases to exist (e.g. end of {} block).
这样做
// gather data needed to initialise object
// note that the compiler will reject using object here
SomeObject object(needed_data);
// do other things with object
//object ceases to exist (e.g. end of {} block).
在c++中,没有什么可以阻止对象在需要时被创建。变量并不局限于在块的顶部或类似的地方声明。
- 具有瞬态资源的RAII类
- 如何仅为一个函数添加延迟
- 以在Qt中的IF语句中设置时间延迟
- 使用RAII在给定次数的迭代后重新分配资源
- 模板化类中静态成员的延迟初始化
- 在 Windows 8/10 技术中完全实时的屏幕捕获,没有延迟
- 将自定义函数传递到基抽象类中以延迟执行
- 我希望改进或要求我目前的延迟/睡眠方法。C++
- 在文件夹迭代上实现 RAII
- 如何在 c++ 中延迟?
- 在 RAII 构造中修改 RVO 值是否安全?
- 如何测量管道延迟?
- 获取毫秒延迟的错误值
- C++异常被捕获延迟,可能导致这种情况的原因是什么?
- 我的子类的属性是延迟初始化的
- RAII 等效于 FIFO 发布订单
- 为什么有些延迟加载 DLL 会立即使用 FFMPEG 卸载?
- 代码战士的延迟
- 延迟加载可以被视为RAII的一个例子吗
- 如何实现RAII +延迟初始化