Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++17: A temporary object never destroyed

struct Base {
    Base() {
        std::cout << "Inside:  " << __PRETTY_FUNCTION__ << std::endl;
    }
    ~Base() {
        std::cout << "Inside:  " << __PRETTY_FUNCTION__ << std::endl;
    }
};

struct BaseWrapper {
    const Base &b;
};

int main()
{
    {
        auto *w = new BaseWrapper{{}};
        std::cout << "Inside:  " << __PRETTY_FUNCTION__ << std::endl;
        delete w;
    }
    return 0;
}

The above code works as I expected when I compile it with C++11 or C++14, but when I compile it with C++17, it gives me something like this:

Inside:  Base::Base()                                                                                                                                                              
Inside:  int main()

As you can see, Base::~Base() was never called. Which doesn't make much sense to me. I have tested this code with GCC 7.3.0 on Ubuntu 18.04.1 LTS, and also with OnlineGDB. They all give the same result.

I'm just wondering if this is a new feature in C++17 or it is a bug?

Update: I'm well aware that w->b is a dangling reference. Actually, I deliberately wrote this piece of code just to show that. Then, I found this issue while testing it.

What I really want to know is how severe this issue is, in case I have to stick with GCC 7.3? or if there is any other ways to reproduce the same issue? or the defect report?

like image 497
Yang Yang Avatar asked Oct 17 '25 19:10

Yang Yang


1 Answers

Clearly, a temporary that is created but not destroyed is a compiler bug - unless the standard says the behaviour is undefined. The example is well defined however. The relevant rules from the standard [class.temporary]:

When an implementation introduces a temporary object of a class that has a non-trivial constructor ([class.default.ctor], [class.copy.ctor]), it shall ensure that a constructor is called for the temporary object. Similarly, the destructor shall be called for a temporary with a non-trivial destructor ([class.dtor]). Temporary objects are destroyed as the last step in evaluating the full-expression ([intro.execution]) that (lexically) contains the point where they were created. ...

There are three contexts in which temporaries are destroyed at a different point than the end of the full-expression. ...

The third context is when a reference is bound to a temporary object ...

The exceptions to this lifetime rule are:

  • ...

  • A temporary bound to a reference in a new-initializer ([expr.new]) persists until the completion of the full-expression containing the new-initializer.

like image 200
eerorika Avatar answered Oct 19 '25 10:10

eerorika



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!