使用std :: pair优化返回值

时间:2018-10-10 19:50:58

标签: c++ std-pair copy-elision rvo nrvo

我目前对C ++ 17的保证RVO及其含义感到困惑。我了解要使NRVO发挥作用,我需要确保

  1. 通过函数和

  2. 的所有可能的返回路径返回一个对象的同一实例。
  3. 使用调用方的函数调用初始化关联的对象

考虑一个装饰最简单的类Widget,我想分配一对没有副本的Widget,然后将其返回

#include<iostream>
#include<utility>

struct Widget {
  Widget() { std::cerr << "Default ctor" << std::endl; }
  explicit Widget(int i) { std::cerr << "custom ctor" << std::endl; }
  Widget(Widget const &) { std::cerr << "copy ctor" << std::endl; }
  Widget(Widget &&) { std::cerr << "move ctor" << std::endl; }
  Widget &operator=(Widget const &) { std::cerr << "copy assign" << std::endl; }
  Widget &operator=(Widget &&) { std::cerr << "move assign" << std::endl; }
  int i_;
};

auto foo(){
  std::pair<Widget,Widget> w;  // default construction
  auto &[w1,w2] = w;
  // do something with w1 and w2
  return w;
}

int main(){
  auto f = foo();
}

没有复制,但是现在我尝试使用make_pair

auto foo(){
  auto w = std::make_pair<Widget,Widget>({},{}); // Awkward syntax and move construction
  auto &[w1,w2] = w;
  // do something with w1 and w2
  return w;
}

如果我想使用make_pair,这真的是唯一可行的选择吗?与第一个功能相比,为什么还要涉及移动构造?

1 个答案:

答案 0 :(得分:3)

我认为您的问题的前提是错误的。

  

如果我想使用make_pair,这真的是唯一可行的选择吗?

您为什么在这里使用std::make_pair

auto w = std::make_pair<Widget,Widget>({},{}); // Awkward syntax and move construction

这确实是尴尬的语法。让我解释一下为什么我会这样...

std::make_pair的{​​{3}}(强调我的):

  

创建一个std :: pair对象,从参数类型推导目标类型

std::make_pair的唯一目的是推导其参数的类型,例如

std::pair<int,int> x;                         
x = std::pair<int,int>(3,3);     // not nice      
x = std::make_pair(3,3);         // ok

默认构造对时,您知道其类型,就不必重复模板参数

std::pair<int,int> a = std::pair<int,int>();  // awkward 

都不希望使用非默认构造(只需使用auto即可,它的唯一作用是必须在同一行代码中的其他位置拼写该类型)

std::pair<int,int> a{5,4}; // no move/copy

底线:

另一种选择是在不需要时不使用std::make_pair