我目前对C ++ 17的保证RVO及其含义感到困惑。我了解要使NRVO发挥作用,我需要确保
通过函数和
使用调用方的函数调用初始化关联的对象
考虑一个装饰最简单的类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,这真的是唯一可行的选择吗?与第一个功能相比,为什么还要涉及移动构造?
答案 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
。