1

根据 Herb Sutter 的说法,下面的代码无法编译。请参阅此站点http://www.gotw.ca/gotw/066.htm,我从中提取了以下文本,涉及function-try-blocks

走向一些道德

顺便说一句,这也意味着构造函数函数try-block的唯一(仅重复)可能用途是转换从基子对象或成员子对象抛出的异常。这是道德#1。接下来,道德#2 说析构函数-try-blocks 完全没用——

“ - 可是等等!” 我听到有人从房间中间打断。“我不同意道德#1。我可以想到构造函数尝试块的另一种可能用途,即释放在初始化列表或构造函数主体中分配的资源!”

对不起,没有。毕竟,请记住,一旦进入构造函数 try-block 的处理程序,构造函数主体中的任何局部变量也已经超出范围,并且可以保证不再存在基子对象或成员对象。你甚至不能参考他们的名字。要么你的对象的部分从未被构建,要么那些被构建的部分已经被销毁。所以你不能清理任何依赖于引用类的基类或成员的东西(无论如何,这就是基类和成员析构函数的用途,对吧?)。

假设这个引用,下面的代码不应该编译,因为在进程运行到子句cat时对象已经被破坏了。catch但它确实如此,至少对于 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;
}
4

3 回答 3

2

我不认为 Herb Sutter 实际上是在说它不会编译。他只是在解释标准对这种情况的说明(15.3.10)的后果:

在处理程序中为该对象的构造函数或析构函数的函数尝试块引用对象的任何非静态成员或基类会导致未定义的行为

于 2011-12-03T12:08:34.283 回答
1

假设这个引用,下面的代码不应该编译......

好吧,他没有说他们永远不会编译。如果有的话,我将引用解释为“这样做是未定义的”。未定义的行为被允许产生任何结果——直到并包括成功编译,以及稍后做令人惊讶的事情。

于 2011-12-03T12:06:17.463 回答
0

编译器是不同的,并且还有一些开关可以确定编译器对其正在编译的代码的严格程度。此代码肯定会导致错误(段错误等)。尝试启用编译器的所有开关以强制它找到它。

于 2011-12-03T12:04:04.540 回答