С++ 11 передать вектор в конструктор

Я весь день читаю об эффективном способе передачи аргументов, и я в замешательстве. Я хочу передать такой вектор:

Foo f({1,2,3});

Мне просто нужно инициализировать переменную _member с переданным вектором. Теперь вопрос в том, как должен выглядеть мой конструктор:

// pass by value
Foo (vector<int> vec) : _member{vec} {}

// const reference
Foo (const vector<int>& vec) : _member{vec} {}

// rvalue reference
Foo (vector<int>&& vec) : _member{std::move(vec)} {}

Ответ 1

Самый простой подход - взять вектор по значению и переместить его:

Foo (vector<int> vec) : _member{std::move(vec)} {}

По сравнению с парой перегрузок const vector<int>&/vector<int>&& вы платите за один дополнительный ход (что очень дешево для векторов), но не нужно писать два конструктора (которые могут быстро взорваться, если вы имеют более одного параметра).

Ответ 2

В настоящее время во многих кругах проходит по модам. Я думаю, что это хороший выбор для конструкторов по разным причинам, поэтому я согласен с T.C. ответ. Однако, более широкий вопрос о наилучшем способе передачи аргументов (к неконструкторским функциям), я редко рекомендую передавать по значению. Я действительно очень рекомендую слушать эту часть беседы с Herb Sutter по теме: https://youtu.be/xnqTKD8uD64?t=51m34s.

Подводя итог, за пределами конструкторов: pass by value дает худшие гарантии производительности по сравнению с простым проходом by const-ref, он дает худшую производительность, чем перегрузки const-ref/rvalue-ref во всех случаях, это делает его сложнее для предоставления исключений, он разрезает полиморфные типы, он не может использоваться, когда копирование является условным.

В большинстве ситуаций вы либо не заботитесь о производительности по причине, либо заботитесь о многом. В первом случае использование const-ref проще и проще. Во втором случае пропуск по значению недостаточно хорош. Опять же, имейте в виду, что конструкторы различны по нескольким причинам (они перемещают конструкцию, а не переносят назначение, они принимают много аргументов, которые сильно влияют на количество перегрузок, которые вам нужны).

К сожалению, такого простого ответа на этот вопрос нет. В конечном счете оба подхода достаточно хороши, но я думаю, что для освоения С++ вы хотите знать плюсы и минусы обоих.

Ответ 3

В этом конкретном случае вы передаете rvalue, поэтому третий вариант является лучшим.