简体   繁体   中英

Will there be a temporary for the returned value that gets destroyed?

I am a bit confused about new rules about copy elision and actually I am not even sure if it applies in this case. I have this:

template <typename T> struct foo {
    T t;
    foo(const T& t) : t(t) {}
    ~foo() { std::cout << "destructor \n"; }
}

template <typename T> foo<T> make_foo(const T& t) { return {t}; }

where make_foo is only to allow deducing the parameter (in the real code t is a lambda, but I left it out here for the sake of simplicity, or rather for the sake of confusion, sorry for that) as in

auto x = make_foo(123);

Now I need to be absolutely sure that foo s destructor is called exactly once: when x goes out of scope. I am afraid this is a unclear-what-you-are-asking question, but if it is that obvious that there wont be any temporary foo , that would be answer enough ;).

In C++11, can I be certain that there wont be a temporary foo in make_foo that will be destroyed? The destructor should be called only when x goes out of scope.

As correctly pointed out in a comment, this question is the Y part of a XY question and the X part is that I want to implement some end of scope functionality. The destructor of foo has some side effects (in the example the cout ) that should be called at the end of scope of x but not in make_foo in case there would be some temporary foo .

In C++11 copy elision even for nameless temporary only allowed not mandated. It's described here copy elision . It is mandated since C++17.

Also in C++17 you will have automatic deduction guides, so you will not need such a construction.

And you can test your compiler, because most of modern compilers will elide copying here.

Since C++17 there is guaranteed to be no temporary.

In C++14 and earlier, there must be an accessible copy/move constructor, and it is optional to the compiler whether or not there is actually a temporary.

As far as I'm aware, the only compiler that would actually manifest a temporary is older versions of MSVC in Debug mode.

In your case to be sure that destructor will not be called for unnamed object you can bind return value to const reference . To clarify what happens if we not rely on copy elision:

template <typename T> foo<T> make_foo(const T& t) { return {t}; }

In this function, return object will not be constructed in scope of that function. It will create temporary unnamed object out of the scope. If you will bind return value to a new named object move constructor will be called(or copy if move is not defined) to create you new object from returned temporary . However if you bind returned temporary to const reference it will be strictly bound to that reference and no new objects will be constructed and temporary will not be destructed till that reference is out of the scope.

EDIT: To not mislead you. Constructor for temporary called in function scope, but lifetime of that temporary will indeed be prolonged to lifetime of const reference

If you need more info you can check this answer. It refers to the C++ standard.

Does a const reference prolong the life of a temporary?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM