I think the relevant part of the C++20 standard is [stmt.return], which says
The copy-initialization of the result of the call is sequenced before the destruction of temporaries at the end of the full-expression established by the operand of the return statement, which, in turn, is sequenced before the destruction of local variables (8.7) of the block enclosing the return statement
So the result of the function call (the return value) should be constructed first, then foo
is destroyed. Since the returned value is constructed before foo
's destructor is run, the result should be 0.
The [class.copy.elision] section says
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects.
So both compilers can be considered correct.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…