Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
445 views
in Technique[技术] by (71.8m points)

c++ - Return std::tuple and move semantics / copy elision

I have the following factory function:

auto factory() -> std::tuple<bool, std::vector<int>>
{
    std::vector<int> vec;
    vec.push_back(1);
    vec.push_back(2);

    return { true, vec };
}

auto [b, vec] = factory();

In the return statement is vec considered an xvalue or prvalue and therefore moved or copy elided?

My guess is no, because the compiler, when list-initializing the std::tuple in the return statement, still doesn't know that vec is going to be destroyed. So maybe an explicit std::move is required:

auto factory() -> std::tuple<bool, std::vector<int>>
{
    ...
    return { true, std::move(vec) };
}

auto [b, vec] = factory();

Is it that really required?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In the return statement is vec considered an xvalue or prvalue and therefore moved or copy elided?

vec is always an lvalue. Even in the simple case:

std::vector<int> factory() {
    std::vector<int> vec;
    return vec;
}

That is still returning an lvalue. It's just that we have special rules that say that we just ignore the copy in this case when we're returning the name of an automatic object (and another special rule in the case that copy elision doesn't apply, but we still try to move from lvalues).

But those special rules only apply to the return object; case, they don't apply to the return {1, object}; case, no matter how similar it might look. In your code here, that would do a copy, because that's what you asked for. If you want to do a move, you must do:

return {1, std::move(object)};

And in order to avoid the move, you must do:

auto factory() -> std::tuple<bool, std::vector<int>>
{
    std::tuple<bool, std::vector<int>> t;

    auto& [b, vec] = t;
    b = true;
    vec.push_back(1);
    vec.push_back(2);
    return t;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...