0

I got some code look like this

struct A
{
    int i;
    A(int i) : i(i) {}
    ~A()
    {
        cout << "destroy " << i << endl;
    }
};
using p = shared_ptr<A>;
p f(int i)
{
    return make_shared<A>(i);
}
int main()
{
    auto i = f(1);
    cout << "a" << endl;
    p && j = f(2);
    cout << "a" << endl;
    p && k = move(f(3));
    cout << "a" << endl;
    auto l = move(f(4));
    cout << "a" << endl;
    p ptr = make_shared<A>(5);
    auto && a = move(ptr);
    cout << "a" << endl;
}

and the output is

a
a
destroy 3
a
a
a
destroy 5
destroy 4
destroy 2
destroy 1

I don't understand why move a function's return value to a rvalue reference cause destruction. But put it directly to a rvalue reference is ok.

The problem is actually found with std::get<> of a std::tuple. I have a function that return a tuple of two shared_ptr and use std::get<> to access the element. But I found that auto && i = get<0>(f()) will cause error but auto i = get<0>(f()) won't. Then I find a similar but simpler situation for std::move

3
  • Please do not ask XY questions. If you want to query about some std::get<> usage with a std::tuple, create a separate question for that. Commented May 4, 2020 at 16:52
  • 2
    @KamilCuk: it is a legitimate question about something that can be baffling sometimes. Commented May 4, 2020 at 17:05
  • My compiler emits warnings on misusing move for the move(f(3)) and move(f(4)) cases. Commented May 4, 2020 at 17:59

3 Answers 3

2
p && j = f(2);

Here, f returns a prvalue of type std::shared_ptr<A>. When you bind a reference to a prvalue it extends the lifetime of the prvalue to be that of the reference. That means that the object returned by f will have the same lifetime as j.

p && k = move(f(3));

Here, once again f returns a prvalue. std::move's parameter binds to that prvalue, extending its lifetime to the lifetime of the parameter. std::move does not return a prvalue though. It returns an xvalue. Lifetime extension does not apply to xvalues, so the object returned by f gets destroyed as soon as std::move's parameter's lifetime ends. That is, it gets destroyed when std::move returns. k then becomes a dangling reference.

Sign up to request clarification or add additional context in comments.

1 Comment

Lifetime extension does apply to some xvalues, though it is true that it does not apply in this case. See stackoverflow.com/a/55576254/481267
2

Let’s go through these one by one:

auto i = f(1); // (1)

This creates a local variable i (not a reference) initialized with the return value of f(1). This is OK. The lifetime of i is until the end of the block.

p && j = f(2); // (2)

This initializes the reference j with a reference to the object returned by f(2), and this extends the lifetime of the value returned by f(2), so this is OK. The lifetime of j is until the end of the block.

p && k = move(f(3)); // (3)

This initializes the reference with a reference to the object returned by move, no lifetime extension occurs since the value returned by move is a reference to the temporary returned by f(2) (and not a temporary object), but the temporary returned by f(2) dies as soon as k is initialized, since its lifetime is not extended (it’s not assigned to a reference variable), and k ends up being a dangling reference.

auto l = move(f(4)); // (4)

Same as (1), the move is useless. The lifetime of l is until the end of the block.

p ptr = make_shared<A>(5); // (5)

This is a local variable initialization. The lifetime of ptr is until the end of the block.

auto && a = move(ptr);

a is a reference to ptr. This does not change the lifetime of ptr.

Comments

1

Because by using std::move you've turned the return value into a reference. And not a const reference, so it's a temporary.

So no copy takes place and as soon as the line ends, the return value is destroyed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.