是否有可能做RAII没有例外

Is it possible to do RAII without exceptions?

本文关键字:RAII 有可能 是否      更新时间:2023-10-16

如果在对象的构造中需要获得的资源可能失败,如果局部编码标准禁止异常,那么可能做RAII吗?

如果是,在这种情况下,处理资源获取失败的规范方式是什么?

我一般不会使用无效对象方法,因为我认为这是糟糕的设计。在构造之后,对象必须处于建立不变量的状态(这是构造函数应该服务的唯一目的)。考虑一个类strange_vector实现了类似于std::vector的东西,但是在调用strange_vector<int>(10, 0)之后,由于分配失败,该对象将处于不可用状态。

相反,我会将构造函数声明为私有,并使用一个工厂方法,该方法返回一个可选的:
class file
{
public:
    ~file() {fclose(m_file);}
    static std::optional<file> open(std::string const& filename)
    {
        auto f = fopen(filename.c_str(), "r");
        if (f)
        {
            return std::make_optional<file>(f);
        }
        else
        {
            return std::nullopt;
        }
    }
private:
    file(FILE* file);
    FILE* m_file;
};
异常处理的最大好处之一是(除了解耦错误处理和正常代码路径之外)您不会意外地忽略它们。如果需要这样做,您可以创建自己的类,类似于optional,当没有使用有效对象初始化时,记录错误消息并终止程序(或任何其他合理的错误处理)。我想a . Alexandrescu有一个关于系统错误处理的演讲,他实现了一个类Expected<T>,其中包含T类型的值或异常。你可以使用这个基,而不是在那里添加错误处理。

std::optional还不是标准的一部分,但是您可以很容易地从最近的编译器、boost或其他库中获得实现。

您总是可以创建一个bool valid(void)方法。然后,构造函数可以设置适当的条件,在代码中,您可以在构造之后检查这是否有效。

class foo
{
public:
    foo(const char *Filename)
    {
        mValid = false;
        if(fopen(Filename) == NULL)
           return;
        mValid = true;
    }
    bool valid(void) { return mValid; }
    private:
        bool mValid;
};
void myfunc(void)
{
    foo fl("myfile");
    if(!fl.valid())
    {
        printf("Errorn");
        return;
    }
}