销毁返回对象

Destruction of returned object

我正在阅读 C++17 standard draft 中第 18 节异常处理的第 18.2 节构造函数和析构函数,其中有一个示例(第 384 页)。我试图了解在 try 块内返回的对象 A 的破坏发生在哪里,但找不到。所以我复制了这个例子,添加了一些打印并看到那个对象的 dtor 从未被调用过。我在这里错过了什么?有人请解释这里发生了什么。

#include <stdio.h>

struct A {
    int a_;
    explicit A(int a):a_(a) {
        printf("A(%d)'s ctor\n", a_);
    }
    ~A() {
        printf("A(%d)'s dtor\n", a_);
    }
};

struct Y { ~Y() noexcept(false) {
    printf("y's dtor\n");
    throw 0; } };

A f() {
    try {
        A a(23);
        Y y;
        A b(56);
        return A(100); // #1 who destructs this ??
    } catch (...) {
        printf("handling exception..\n");
    }
    printf("At line %d now..\n", __LINE__);
    return A(200); // #2
}

int main() {
    auto ret = f();
    printf("f returned A(%d) object\n", ret.a_);
    return 0;
}

以上代码输出如下:

A(23)'s ctor                                                                                                                                                  
A(56)'s ctor                                                                                                                                                  
A(100)'s ctor                                                                                                                                                 
A(56)'s dtor                                                                                                                                                  
y's dtor                                                                                                                                                      
A(23)'s dtor                                                                                                                                                  
handling exception..                                                                                                                                          
At line 34 now..                                                                                                                                              
A(200)'s ctor                                                                                                                                                 
f returned A(200) object                                                                                                                                      
A(200)'s dtor                                                                                                                                                 


...Program finished with exit code 0

一般来说,函数的调用者负责销毁函数的 return 值,但具体细节是平台 C++ ABI 的一部分。

在大多数 ABI 上,调用一个 return 具有重要值(任何不能安全地放入一个或两个寄存器中的值)的函数,是通过传递一个隐藏的额外参数来完成的,该参数指定return 应构造值。调用者在其框架中为 return 值分配 space 并传递指向该 space.

的指针

根据 C++17 标准 [except.ctor]/2:

If an exception is thrown during the destruction of temporaries or local variables for a return statement, the destructor for the returned object (if any) is also invoked. The objects are destroyed in the reverse order of the completion of their construction.

然后有一个说明性的例子(你稍微修改了一下)来演示:在 Y 析构函数抛出之后,接下来发生的事情是 A(100) 对象应该被销毁,所以你应该看到销毁消息。

发布的输出表明存在编译器错误。这与报告为 LLVM bug 12286 and gcc bug 33799.

的问题非常相似

后者被标记为已在 GCC 10 中修复(在 2007 年首次报告之后!)。但是,使用 10.0.1 20200418 (experimental) on Godbolt 版本进行测试:即使 33799 错误报告中的测试用例已修复,但此问题中的代码仍未修复。我在该错误报告中添加了关于此示例的评论。