我刚接触过C++,目前正在学习RAII (资源获取是初始化)模式。我很好奇如何处理他们需要等待的资源。
在Java中,可能要做的事情是:
MyClass obj = new MyClass();
new Thread(
() -> obj.initialize(); // resource acquisition
).start()
...
if (obj.initialized()) {
// Use object
}换句话说,我们可以在后台进行时间密集型的资源获取.
我们如何在C++和RAII中做到这一点?或者这是RAII的限制?
发布于 2019-12-29 16:46:57
RAII意味着资源由某个对象定义。理想情况下,该对象的构造函数获取资源,析构函数释放它。在对象有效的时间内,可以使用对象与资源进行交互。
如果一个资源“需要等待”,那么根据RAII的规则,这意味着您还没有一个表示该资源的对象。相反,您有一个表示将来可用的资源的对象。
这就是为什么C++称这种类型为std::future。它是一个模板,参数是正在等待创建的对象的类型。
从概念上讲,future只是将对象(或异常)从生成它(可能是异步)的代码块转发给接收方的一种方式。
现在给出您的示例,我们需要从initialize中删除MyClass,并使之成为一个返回MyClass实例的函数。它可以是MyClass的静态成员,也可以是名称空间范围内的函数。
所以代码本质上是这样的:
auto future = std::async(initialize);
...
if(future.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
MyClass resource = future.get(); //The `future` is now empty. Any exceptions will be thrown here.
//use resource
}发布于 2019-12-29 15:52:40
当可能获得一个尚未准备好使用的对象时,RAII解决反模式问题。尤其是,您的Java代码有相同的反模式-- MyClass的用户很容易在构造对象之后忘记运行initialize方法。
当需要进行复杂初始化时,执行RAII的最简单方法是通过工厂方法。将可能不安全的构造函数设置为私有,并公开将为您构造和初始化对象的公共静态函数。特别是,如果您想同时运行初始化,没有什么可以阻止您将该工厂方法的返回类型转换为std::future或类似的方法。
关键是RAII的目的--不可能获得未初始化的资源。通过创建获取始终初始化资源的函数的唯一方法,您将获得RAII。
https://stackoverflow.com/questions/59519943
复制相似问题