Return std::tuple 和移动语义/复制省略
Return std::tuple and move semantics / copy elision
我有以下工厂函数:
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
,因此被移动或复制?
我的猜测是不会,因为编译器在 return 语句中对 std::tuple
进行列表初始化时,仍然不知道 vec 将被销毁。所以可能需要明确的 std::move:
auto factory() -> std::tuple<bool, std::vector<int>>
{
...
return { true, std::move(vec) };
}
auto [b, vec] = factory();
真的需要吗?
In the return statement is vec
considered an xvalue or prvalue and therefore moved or copy elided?
vec
总是 一个左值。即使在简单的情况下:
std::vector<int> factory() {
std::vector<int> vec;
return vec;
}
即仍然返回一个左值。只是在复制省略不适用的情况下我们有 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,但我们仍然尝试从左值移动)。
但是那些特殊规则只适用于return object;
的情况,它们不适用于return {1, object};
的情况,无论它多么相似看。在您的代码中,这将复制一份,因为这就是您所要求的。如果你想做一个动作,你必须做:
return {1, std::move(object)};
为了避免移动,您必须这样做:
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;
}
我有以下工厂函数:
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
,因此被移动或复制?
我的猜测是不会,因为编译器在 return 语句中对 std::tuple
进行列表初始化时,仍然不知道 vec 将被销毁。所以可能需要明确的 std::move:
auto factory() -> std::tuple<bool, std::vector<int>>
{
...
return { true, std::move(vec) };
}
auto [b, vec] = factory();
真的需要吗?
In the return statement is
vec
considered an xvalue or prvalue and therefore moved or copy elided?
vec
总是 一个左值。即使在简单的情况下:
std::vector<int> factory() {
std::vector<int> vec;
return vec;
}
即仍然返回一个左值。只是在复制省略不适用的情况下我们有 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,但我们仍然尝试从左值移动)。
但是那些特殊规则只适用于return object;
的情况,它们不适用于return {1, object};
的情况,无论它多么相似看。在您的代码中,这将复制一份,因为这就是您所要求的。如果你想做一个动作,你必须做:
return {1, std::move(object)};
为了避免移动,您必须这样做:
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;
}