我曾经认为在C++中,如果构造函数抛出异常,则不会调用此"部分构造"类的析构函数.
但似乎在C++ 11中它不再是真的:我使用g ++编译了以下代码,并将" X destructor" 打印到控制台.为什么是这样?
#include <exception>
#include <iostream>
#include <stdexcept>
using namespace std;
class X
{
public:
X() : X(10)
{
throw runtime_error("Exception thrown in X::X()");
}
X(int a)
{
cout << "X::X(" << a << ")" << endl;
}
~X()
{
cout << "X destructor" << endl;
}
};
int main()
{
try
{
X x;
}
catch(const exception& e)
{
cerr << "*** ERROR: " << e.what() << endl;
}
}
Run Code Online (Sandbox Code Playgroud)
产量
Standard out: …Run Code Online (Sandbox Code Playgroud) class X
{
public:
X() {};
X(int) : X() { throw std::exception(); }
X(double) { throw std::exception(); }
~X();
};
Run Code Online (Sandbox Code Playgroud)
动态记忆怎么样?通常,构造函数中的异常意味着对象未完全构造,因此内存是干净的并且不会丢失.
但是上一个问题中的论点是在委托完成后对象完全构造(或完全初始化).这对回收内存有何影响?我希望记忆仍然是清洁的!
int main()
{
new X(5); // new called
// delete called because delegate completed.
// I assume:
// Memory re-claimed (because constructor did not complete)
// I assume the C++11 standard adjusted to compensate.
// As a constructor did complete.
}
Run Code Online (Sandbox Code Playgroud)
比较也是:
int main()
{
new X(5.0); // new called
// Delete **NOT** called …Run Code Online (Sandbox Code Playgroud) 根据有关委托构造函数的问题,当第一个构造函数完成时,将调用析构函数。
\n这与下面的代码是一致的:
struct test {\n test() { std::cout << "default constr\\n"; }\n test(int) : test() { std::cout << "argument constr\\n"; throw int{}; }\n ~test() { std::cout << "destr\\n"; }\n};\n\nint main()\n{\n try {\n test t{3};\n } catch(...)\n {\n std::cout << "caught\\n";\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n输出:
\ndefault constr\nargument constr\ndestr\ncaught\nRun Code Online (Sandbox Code Playgroud)\n但是,Stroustrup 在他的书中(第 4 版,第 503 页)说了以下内容:
\n\n\n在对象的构造函数完成之前,对象不会被视为已构造 (...)。使用委托构造函数时,在委托构造函数完成\xe2\x80\x93 之前,对象不会被视为已构造,仅完成委托构造函数是不够的。除非其原始构造函数完成,否则不会为对象调用析构函数。\n
\n
是我误读了还是他有别的意思?
\n