0

I'm getting the different behaviour on different compliler, on GCC temporary object and local variable are destroyed in the end of an expression but on MSVC compiler, local variable and temporary object are destroyed at the end of function. why i'm getting this different behaviour ? see live demo

struct X{ 
    X() 
    {
        std::cout << "X::X() " << '\n';
    }

    X(const X& arg)
    {
        std::cout << "X::Copy" << '\n';
    }

    X(X&& arg)
    {
        std::cout << "C::move" << '\n';
    }
        
    ~X(){ std::cout << "Goodbye, cruel world!\n"; }

};
X  f(X  x){
    X arg{};
    std::cout << "Inside f()\n";
    return x;
}
void g(X  x){
    std::cout << "Inside g()\n";
}

int main()
{
    X arg{};
    g(f(arg));
}

GCC output:

X::X() 
X::Copy
X::X() 
Inside f()
C::move                 // on which line it is caling move construtor ?
Goodbye, cruel world!   // which object does get destructed ?, on which line ?
Inside g()
Goodbye, cruel world!
Goodbye, cruel world!
Goodbye, cruel world!

MSCV output:

X::X() 
X::Copy
X::X() 
Inside f()
C::move
Goodbye, cruel world!
Goodbye, cruel world!
Inside g()
Goodbye, cruel world!
Goodbye, cruel world!
mn_op
  • 107
  • 6
  • 2
    Copy elision is likely causing confusion here. – sweenish Sep 21 '22 at 15:54
  • @sweenish Doesn't appear to be the case. Both outputs show 4 constructors and 4 destructors being called. – Igor Tandetnik Sep 21 '22 at 16:00
  • @sweenish that's not the case, [see if we disable copy elision](https://godbolt.org/z/T1MTe1xW3) – mn_op Sep 21 '22 at 16:14
  • 1
    See [dupe](https://stackoverflow.com/a/73704736/12002570): *"It is implementation-defined whether the lifetime of a parameter ends when the function in which it is defined returns or at the end of the enclosing full-expression. "* – Jason Sep 21 '22 at 16:15
  • [Dupe1](https://stackoverflow.com/questions/73704628/why-is-the-destructor-of-a-function-parameter-not-called-at-the-end-of-the-funct), [Dupe2](https://stackoverflow.com/questions/48453898/late-destruction-of-function-parameters) and [Dupe3](https://stackoverflow.com/questions/51251557/when-the-object-destructed-while-i-pass-the-argument-by-value). – Jason Sep 21 '22 at 16:16
  • @sweenish It's not due to copy elision. – Jason Sep 21 '22 at 16:17
  • @JasonLiam hey i have two doubts, i added in GCC output context ? can you please have a look at them, and explain ? – mn_op Sep 21 '22 at 16:33
  • 1
    @mn_op In both compilers the move ctor is called for the return statement `return x;`. I've explained this in great detail [here](https://stackoverflow.com/a/71934476/12002570). It is because of the *implicit move rule*. Now coming to your second doubt, in gcc the very first destructor call that you see(that is just below the move ctor call) is for the destruction of local object `arg`. – Jason Sep 21 '22 at 16:45
  • @JasonLiam so, why there is no statement, for the g() function parameter, like f() have printed ***X::copy*** for its parameter ? – mn_op Sep 21 '22 at 23:41
  • @JasonLiam if this is because of copy elision, then why there is no copy elision for f() parameter. does both parameter expression have some difference between f() and g() respectively ? – mn_op Sep 21 '22 at 23:51
  • @mn_op Because `f(arg)` is a temporary and from c++17 due to mandatory copy elision the parameter `x` of function `g` is created directly. You can confirm this with C++11 by using `-fno-elide-constructors` flag as i also said in one of your previous [post](https://stackoverflow.com/a/73782728/12002570). See [demo](https://godbolt.org/z/sqdTdqbvK) with this flag. – Jason Sep 22 '22 at 04:01
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/248240/discussion-between-mn-op-and-jason-liam). – mn_op Sep 22 '22 at 05:09

0 Answers0