我知道构造函数可以抛出异常,当发生不好的事情时,这可能是一件好事。但是当构造函数抛出时,假设构造函数中的所有资源都得到了适当的管理(例如使用 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;
}
};
当构造函数抛出时,v
和 s
的析构函数被调用,对吗?因此,感谢 std::vector
和 std::string
的析构函数,A
的构造函数不会泄漏任何资源,然后它提供至少基本保证。我说得对吗?
我的问题是:我可以说这个构造函数提供了强有力的保证吗? 另外,是否值得记录构造函数的保证?
我的猜测:它确实有很强的保证。由于对象在尝试构造它之前不存在,如果构造函数失败,无论如何都不会创建对象,那么操作(构造对象)没有效果,一切都在构造函数开始之前。
如果我猜对了:
- 当施工方只提供基本保证而不提供强力保证时?
最佳答案
你是对的。被构造函数修改的对象只有s
和v
,它们在构造函数被调用前不存在,调用退出后也不存在异常(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/