c++ - 抛出的(默认)构造函数中的异常保证应该是什么?

标签 c++ exception constructor

我知道构造函数可以抛出异常,当发生不好的事情时,这可能是一件好事。但是当构造函数抛出时,假设构造函数中的所有资源都得到了适当的管理(例如使用 RAII ),哪一个是确切的异常保证(基本的,强的)?

详细来说,我正在记录我的代码并编写每个成员函数的异常保证(并尝试编写安全异常代码)。

例如,如果我有这样一个类:

struct A
{
    std::string s;

    A()
    {
        std::vector<int> v(5);
        s = "some text";

        /* do a lot of fascinating things */

        if (error)
            throw 1;
    }
};

当构造函数抛出时,vs 的析构函数被调用,对吗?因此,感谢 std::vectorstd::string 的析构函数,A 的构造函数不会泄漏任何资源,然后它提供至少基本保证。我说得对吗?

我的问题是:我可以说这个构造函数提供了强有力的保证吗? 另外,是否值得记录构造函数的保证?

我的猜测:它确实有很强的保证。由于对象在尝试构造它之前不存在,如果构造函数失败,无论如何都不会创建对象,那么操作(构造对象)没有效果,一切都在构造函数开始之前。

如果我猜对了:

  • 当施工方只提供基本保证而不提供强力保证时?

最佳答案

你是对的。被构造函数修改的对象只有sv,它们在构造函数被调用前不存在,调用退出后也不存在异常(exception)。因此没有可观察到的副作用,并且构造函数提供了强大的异常保证。

什么时候构造函数可以只提供基本保证?可能人为的例子:

class A {
  public:
    A() {
        printf("A is being constructed\n");
        throw std::runtime_error("oh no!");
    }
};

基本保证显然得到支持,但由于存在副作用,因此不支持强保证。 (产生副作用的另一种方法是修改全局变量。)如果构造函数采用参数,则会发生更有趣的事情。另一个可能人为的例子:

class B {
  public:
    A(std::vector<int>&& v): v(std::move(v)), a() {}
  private:
    std::vector<int> v;
    A a;
};

此处,A 的构造函数在 B::v 已经初始化后抛出,因此后者被销毁。调用者仍然有一个有效的 vector ,但它现在是空的。基本保证仍然满足,因为所有对象都处于有效状态,但不是强保证。

关于c++ - 抛出的(默认)构造函数中的异常保证应该是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27737474/

相关文章:

java - EJBCA如何创建用于web服务和java代码之间通信的 keystore (wsdl异常)

android.content.res.Resources$NotFoundException : String resource ID Fatal Exception in Main

c++ - 如何在 C++ 中有效地添加两个 vector

c++ - Codelite MinGW G++ 链接器错误

c++ - Windows 中 _strnicmp 的 LPTSTR 等价物是什么?

c++ - 错误 C4430 : missing type specifier - int assumed. 注意:C++ 不支持我的构造函数的默认整数

constructor - TO 和 MAKE 的目的有何不同,它们记录在何处?

c++ - 如何 Hook 新创建的注册表

c++ - Qt std::runtime_error 等效项

c++ - 使用虚拟继承时初始化基类