Оптимизация возвращаемого значения с помощью std :: pair - PullRequest
0 голосов
/ 10 октября 2018

Я в настоящее время весьма озадачен гарантированным СВО 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?Есть ли какая-либо причина в том, что по сравнению с первой функцией задействована конструкция перемещения?

1 Ответ

0 голосов
/ 11 октября 2018

Я думаю, что предпосылка вашего вопроса неверна.

Это действительно единственно возможная альтернатива, если я хочу использовать make_pair?

Зачем вам использовать std::make_pair здесь?

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

Это действительно неловкий синтаксис.Позвольте мне объяснить, почему я так думаю ...

С cppreference на std::make_pair (подчеркните мое):

Создает объект 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, когда вам это не нужно.

...