Должны ли небольшие простые структуры передаваться по константной ссылке? - PullRequest
18 голосов
/ 23 июля 2010

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

void foo(std::string str);//bad
void foo(const std::string &str);//good

Но сегодня я думал, что, возможно, на самом деле некоторые простые пользовательские типы могут лучше передаваться по значению, например:

class Vector2
{
public:
    float x, y;
    ...constructors, operators overloads, utility methods, etc...
};

void foo(Vector2 pos);
void foo(const Vector2 &pos);//is this really better than by value?
void foo(float x, float y);//after all isn't by value effectively doing this?

Я думаю, что, передав Vector2 по ссылке, это на самом деле дороже, чем передавать по значению, поскольку компилятор теперь использует указатель и разыменование для доступа к const версии Vector2 & pos?

Это так? Простые объекты лучше всего передаются по значению? Где должна быть проведена линия?

Ответы [ 6 ]

8 голосов
/ 23 июля 2010

Да, простые объекты должны передаваться по значению. Линия должна быть проведена в соответствии с архитектурой. В случае сомнений, профиль.

1 голос
/ 23 июля 2010

Один из факторов, о которых я не упомянул, это то, что процедура будет делать с переданным значением.Если подпрограмма не развернута в строке, для манипулирования данными, которые передаются по ссылке, потребуется больше кода, чем для манипулирования данными, которые передаются по значению.Если к полям переданной структуры в среднем будет обращаться меньше одного раза, эти дополнительные издержки будут небольшими по сравнению с издержками на копирование структуры.Если к ним в среднем будет обращаться много раз, вероятно, было бы лучше иметь их в стеке.Если интерфейс уже задан в качестве проходной ссылки для структуры, к которой имеется большой доступ, вызываемой подпрограмме может иметь смысл скопировать все представляющие интерес части.С другой стороны, если вызываемая подпрограмма собирается скопировать большую часть или всю структуру в любом случае, она также может быть передана по значению.

1 голос
/ 23 июля 2010

Более старый, но ясный анализ входных и выходных параметров можно найти по адресу http://www.ddj.com/184403855. Конечно, c ++ 0x устраняет множество таких проблем с семантикой перемещения, но статья предоставляетмного оправданий тому, почему семантика перемещения желательна.

1 голос
/ 23 июля 2010

Как правило, я передаю любой объект, который не является базовым типом данных C, по константной ссылке. Так намного легче запомнить.

1 голос
/ 23 июля 2010

Передача по константной ссылке позволяет избежать строительства нового объекта. Если ваш конструктор нетривиален, например, он выделяет память, вы будете намного лучше проходить по константной ссылке, чем по значению.

В мире C # вы принимаете это решение, выбирая, делать ли что-то классом или структурой. Классы используют ссылочную семантику, а структуры используют семантику значений. Все, что я когда-либо читал, говорит о том, что вы, как правило, должны выбирать, чтобы все было классом, если оно не очень маленькое, то есть порядка 16 байтов. Если вы ищете сокращение времени передачи по значению по сравнению с константной ссылкой в ​​C ++, 16 байтов кажутся разумным порогом.

0 голосов
/ 23 июля 2010

Я думаю, что, передав Vector2 по ссылке, это на самом деле дороже, чем передавать по значению, поскольку компилятор теперь использует указатель и разыменование для доступа к const Vector2 & pos версии

Было бы верно, если бы вы передали объект, где size_of(object) < size_of(pointer_to_object). Например, char const& может быть дороже, чем char

...