返回std :: tuple并移动语义/复制省略 [英] Return std::tuple and move semantics / copy elision

查看:96
本文介绍了返回std :: tuple并移动语义/复制省略的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下工厂功能:

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();

在return语句中, vec 被认为是 xvalue prvalue ,因此被移动或复制了吗?

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

我的猜测是否定的,因为编译器在return语句中对 std :: tuple 进行列表初始化时,仍然不知道vec将被销毁.因此,可能需要显式的std :: move:

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();

真的需要吗?

推荐答案

在return语句中, vec 被认为是xvalue或prvalue,因此被移动或复制了吗?

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

vec 总是 一个左值.即使在简单的情况下:

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

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

still 返回左值.只是我们有特殊规则说我们只是忽略了在这种情况下,当我们返回自动对象的名称(以及另一个特殊规则(如果复制省略不适用,但我们仍然尝试从左值移开).

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).

但是那些特殊规则仅适用于 return对象; 情况下,它们不适用于 return {1,object}; 情况,无论看起来如何相似.在这里的代码中,它将进行复制,因为这就是您要的.如果要移动,必须执行以下操作:

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

这篇关于返回std :: tuple并移动语义/复制省略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆