根据Herb Sutter的说法,下面的代码无法编译。请参阅这个网站http://www.gotw.ca/gotw/066.htm,我从中提取了以下关于function-try-blocks
的文本:
走向道德
顺便说一下,这也意味着唯一的(重复)构造函数-try-block的唯一可能用途是翻译从基类或成员子对象抛出的异常。这是道德# 1。其次,道德#2说析构函数-尝试-块是完全无效——"——但是等等!"我听到有人从房间中间插嘴。"我不同意道德1。我能想到另一个可能的用法构造函数-试块,即释放分配在初始化列表或在构造函数体中!"
对不起,没有。毕竟,记住一旦你进入你的构造函数try-block的处理程序,中的任何局部变量构造函数体也已经超出了作用域,您可以保证不再存在基子对象或成员对象。你甚至不能提到他们的名字。你的物体的各个部分从来没有被建造过,或者那些已经被建造过的摧毁。所以你不能清理任何依赖于引用类的基类或成员(无论如何,这就是基类析构函数和成员析构函数都是for的,对吗?
假设这个引用,下面的代码不应该编译,因为当进程运行到catch
子句时,对象cat
已经被销毁了。但它确实存在,至少在VSC2008中是这样。
class Cat
{
public:
Cat() { cout << "Cat()" << endl; }
~Cat() { cout << "~Cat()" << endl; }
};
class Dog
{
public:
Dog() { cout << "Dog()" << endl; throw 1; }
~Dog() { cout << "~Dog()" << endl; }
};
class UseResources
{
class Cat *cat;
class Dog dog;
public:
UseResources();
~UseResources() { delete cat; cat = NULL; cout << "~UseResources()" << endl; }
};
UseResources::UseResources() try : cat(new Cat), dog() { cout << "UseResources()" << endl; } catch(...)
{
delete cat;
throw;
}
我不认为Herb Sutter实际上是在说它不会编译。他只是在解释标准对这种情况(15.3.10)必须说的后果:
类中对象的任何非静态成员或基类的构造函数或析构函数的函数尝试块的处理程序该对象导致未定义行为。
假设这个引用,下面的代码不应该编译…
好吧,他并没有说它们永远不会编译。如果有的话,我把这句话理解为"这样做是不确定的"。未定义的行为允许有任何结果——直到并包括成功编译,以及以后做一些令人惊讶的事情。
编译器是不同的,也有一些开关决定了编译器对编译代码的严格程度。这段代码肯定会导致错误(segfault等)。试着打开编译器的所有开关来强制它找到这个