使用std :: tie解包返回值会导致额外费用吗?

时间:2019-07-19 17:48:15

标签: c++ c++11 c++17

考虑这两种方法

方法1

std::tuple<TypeA, TypeB> res = function(args);
TypeA & a = std::get<0>(res);
TypeB & b = std::get<1>(res);
// use a and b as you want

方法2

TypeA a;
TypeB b;
std::tie(a, b) = function(args);
// use a and b as you want

我正在考虑这两种方法的优缺点。

方法2会导致额外费用吗?或者也许它们完全等效?

c++17中,结构绑定提供了一种更直观的解包元组的方法

auto [ var1, var2 ] = tuple;

与上面列出的另外两种方法相比,它将带来任何改善吗?还是只是语法糖?

1 个答案:

答案 0 :(得分:2)

我要保证function返回tuple<TypeA, TypeB>。另外,由于我很懒,我将AB用作TypeATypeB的别名。

auto&& [a,b] = function(args);

这是方法1的语法糖。

方法2首先在ab上调用默认构造函数。然后,它使用tuple<A&,B&>=operator=(tuple<A,B>&&)来分配ab。然后将返回值tuple<A,B>中创建的临时function丢弃。

对于某些类型,这些操作没有可观察到的效果,因此不需要编译器执行任何工作。在其他类型中,创建临时对象然后对其进行赋值会产生观察效果。在这种情况下,编译器必须执行这些额外的操作。

优化auto&&[a,b]对于编译器将更加容易,并且它还支持其他一些情况,例如

struct function_retval { int a, int b; };
function_retval function( int arg );

auto&&[a,b] = function(7);

另一个好处是它没有大量您不想在代码中谈论的命名变量。返回值的实际持有者将变为匿名。另外,decltype(a)不是引用,与情况1不同,因为标准实际上是这样引用的,尽管它是引用。

({auto&&只是意味着我不在乎是否将返回值存储在引用或值中;我使用任何function返回的值)。