As far as I know, temporaries should be destroyed at the end of the full expression. However, for this code snippet (godbolt), this is not true for Visual Studio:
#include <cstdio>
struct Foo {
Foo() = default;
Foo(const Foo &) {}
~Foo() {
std::printf("~Foo()\n");
}
};
int foo(Foo f) {
return 0;
}
void bar(int) {
std::printf("bar\n");
}
int main() {
bar(foo(Foo()));
}
This code should print (because the destructor of the Foo() temporary should run after bar returned):
bar
~Foo
However, with MSVC, the code prints:
~Foo
bar
Is this behavior allowed?
In this code, Foo() doesn't create a temporary object. It is a prvalue that is used to directly construct the parameter f. See [dcl.init.general]/16.6.1
The lifetime of a function parameter is governed by [expr.call]/6, which states that
[...] It is implementation-defined whether a parameter is destroyed when the function in which it is defined exits ([stmt.return], [except.ctor], [expr.await]) or at the end of the enclosing full-expression; parameters are always destroyed in the reverse order of their construction. The initialization and destruction of each parameter occurs within the context of the full-expression ([intro.execution]) where the function call appears.
[Example 2: ...]
The parameter f can be destroyed either before or after the body of bar is executed. They're both valid options for the implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With