为什么函数参数的析构函数不是在函数末尾调用,而是在函数调用的完整表达式末尾调用?

Las*_*sie 6 c++

考虑以下示例:

#include <iostream>

struct A
{
    int n = 0;
    A() { std::cout << "A()" << std::endl; }
    A(const A&) { std::cout << "A(const A&)" << std::endl; }
    ~A() { std::cout << "~A()" << std::endl; }
};

int f(A a) { std::cout << "f()" << std::endl; return 1; }

int main()
{
    A a;
    std::cout << f(a) << " was returned from f(A)" << std::endl;
    std::cout << "leaving main..." << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我期望这个程序的输出是:

A()
A(const A&)
f()
~A()
1 was returned from f(A)
leaving main...
~A()
Run Code Online (Sandbox Code Playgroud)

因为当函数返回时,它的参数应该已经被销毁了。例如,如果我们有以下函数:

A* g(A a) { std::cout << "g()" << std::endl; return &a; }
Run Code Online (Sandbox Code Playgroud)

取消引用返回的指针是未定义的行为:

std::cout << g(a)->n << std::endl; // undefined behavior
Run Code Online (Sandbox Code Playgroud)

但输出是:

A* g(A a) { std::cout << "g()" << std::endl; return &a; }
Run Code Online (Sandbox Code Playgroud)

我正在寻找这种行为的解释。

Use*_*ess 7

为什么函数参数的析构函数不是在函数末尾调用,而是在包含函数调用的完整表达式的末尾调用?

根据[expr.call]/7

参数的生命周期是在定义参数的函数返回时结束还是在封闭的完整表达式结束时结束,是由实现定义的。每个参数的初始化和销毁​​都发生在调用函数的上下文中。

所以标准允许这两种行为。

我正在寻找这种行为的解释。

这是标准允许的,这就是您测试的任何编译器选择组织其代码的方式。