Изменить: Новая статья Дейва Абрахама на cpp-next:
Передавать по значению для структур, где копирование дешево, имеет дополнительное преимущество, заключающееся в том, что компилятор может предположить, что объекты не являются псевдонимами ( не те же объекты). Используя pass-by-reference, компилятор не может всегда это предполагать. Простой пример:
foo * f;
void bar(foo g) {
g.i = 10;
f->i = 2;
g.i += 5;
}
компилятор может оптимизировать его в
g.i = 15;
f->i = 2;
, так как он знает, что f и g не имеют одного и того же местоположения. если g была ссылкой (foo & amp;), компилятор не мог этого предположить. так как gi может быть затем сглажено f-> i и должно иметь значение 7. поэтому компилятор должен будет повторно извлечь новое значение gi из памяти.
Для более пратических правил здесь является хорошим набором правил, найденным в статье Move Constructors (рекомендуемое чтение).
«Примитив» означает, что в основном небольшие типы данных, длина которых несколько байтов и не являются полиморфными (итераторы, функциональные объекты и т. д.) или дорогими для копирования. В этой статье есть еще одно правило. Идея состоит в том, что иногда хочется сделать копию (в случае, если аргумент не может быть изменен), а иногда и не нужен (в случае, если кто-то хочет использовать сам аргумент в функции, если аргумент был временным в любом случае , например). В документе подробно объясняется, как это можно сделать. В C ++ 1x этот метод может быть использован изначально с поддержкой языка. До тех пор я бы пошел с вышеуказанными правилами.
Примеры. Чтобы сделать строку в верхнем регистре и вернуть версию в верхнем регистре, нужно всегда передавать по значению: каждый должен взять ее копию (невозможно напрямую изменить ссылку на константу) - так лучше сделайте это как можно более прозрачным для вызывающего и сделайте эту копию раньше, чтобы вызывающий мог оптимизировать как можно больше - как подробно описано в этой статье:
my::string uppercase(my::string s) { /* change s and return it */ }
Однако, если вам не нужно измените параметр в любом случае, возьмите его по ссылке на const:
bool all_uppercase(my::string const& s) {
/* check to see whether any character is uppercase */
}
Однако, если вы предназначаете параметр для записи чего-либо в аргумент, то передайте его по неконстантной ссылке
bool try_parse(T text, my::string &out) {
/* try to parse, write result into out */
}