В c ++ 11 я передал бы все, что планирую «хранить» или «потреблять» с помощью &&.Это приводит к наиболее эффективному коду, но «нарушает» совместимость lvalue и вынуждает меня рассмотреть возможность использования двух (или более) версий каждого метода.К сожалению, по мере увеличения количества аргументов вы получаете взрыв перестановок rvalue и const &, и это делает получение указателей на функции гораздо более «уродливым».
Вместо предоставления двух (или более) перегрузок, одной для lvalues и одной для rvalue, я решил предоставить только перегрузку rvalue, и если пользователь хочет передать lvalue, они переносят с помощью std :: ref (), std :: cref (), std :: move () или мой собственный вспомогательный метод copy (), который делает копию явной и преобразует значение l в значение r.(std :: ref () и std :: cref () могут работать только в том случае, если аргументы являются параметрами шаблона ... в этом случае метод, вероятно, будет использовать std :: forward <> () для обработки автоматического определения перемещенияпротив семантики копирования.
template<typename T>
T copy( const T& v ) { return v; }
Если я пишу метод, который не «хранит» и не «потребляет» входные данные, тогда я использую const &
. Я, вероятно, должен уточнить, что я бы использовалconst & для любых типов, которые не извлекают выгоду из семантики перемещения (без глубоких копий). Но когда вы пишете шаблонный код, вы не хотите делать такое предположение о типе.
Другая практика, которую я рассматриваю, заключается в созданиинекоторые классы «только явное копирование».
class test {
public:
test(){...};
test( test&& t ){...}
private:
template<typename T>
friend T copy(const T&t);
test& operator=(const test&); // not implemented
test( const test& t ){...}
std::vector<char> large_data;
};
int main( int argc, char** argv ) {
test x;
test y = copy(x);
test z = x; // error, test(const test&) is private...
return 0;
}
Я бы использовал это для любого класса, который содержит любые «подвижные члены», такие как строки, векторы, карты и т. д. Технически нет причин, по которым я не мог быне копировать их, но почему бы мне не попытаться переместить семантику везде, где это возможно, если я действительно не хочу копировать? С неявными копиями у компилятора нет способа предупредить меня, что я делаю что-тохинг потенциально дорогой.