使用std :: pair返回值优化

问题描述 投票:0回答:1

我目前对C ++ 17保证的RVO及其含义感到困惑。我明白,要让NRVO加入,我需要确保这一点

  1. 通过函数的所有可能返回路径返回一个对象的同一个实例
  2. 使用呼叫侧的函数调用初始化关联对象

考虑一个最简单的装饰类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,这真的是唯一可行的选择吗?与第一个函数相比,为什么还有移动构造?

c++ std-pair copy-elision rvo nrvo
1个回答
3
投票

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

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

你为什么要在这里使用std::make_pair

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

这真的是笨拙的语法。让我解释为什么我这么认为......

来自qazxsw poi on qazxsw poi(强调我的):

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

cppreference的唯一目的是推断其参数的类型,例如在

std::make_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

© www.soinside.com 2019 - 2024. All rights reserved.