Return std::tuple and move semantics / copy elision

天大地大妈咪最大 提交于 2020-11-24 16:35:17

问题


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?


回答1:


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;
}


来源:https://stackoverflow.com/questions/51521031/return-stdtuple-and-move-semantics-copy-elision

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!