std
предполагает, что объекты-функции и итераторы могут свободно копироваться.
std::ref
предоставляет метод для превращения функционального объекта в псевдоссылку с совместимым operator()
, который использует ссылку вместо семантики значения. Так что ничего особо ценного не потеряно.
Если вас всю жизнь учили брать объекты по эталону, пересмотрите свое мнение. Если нет веских причин, берите объекты по значению. Рассуждать о ценностях гораздо проще; ссылки — это указатели на любое состояние в любом месте вашей программы.
Обычное использование ссылок в качестве указателя на локальный объект, на который не ссылается никакая другая активная ссылка в контексте, где он используется, не является чем-то, что кто-то, читающий ваш код, или компилятор может предположить. Если вы рассуждаете о ссылках таким образом, они не усложняют ваш код до смешного.
Но если вы рассуждаете о них таким образом, у вас будут ошибки, когда ваше предположение будет нарушено, и они будут тонкими, грубыми, неожиданными и ужасными.
Классический пример — количество operator=
, которые прерываются, когда this
и аргумент ссылаются на один и тот же объект. Но любая функция, которая принимает две ссылки или указатели одного типа, имеет ту же проблему.
Но даже одна ссылка может сломать ваш код. Давайте посмотрим на sort
. В псевдокоде:
void sort( Iterator start, Iterator end, Ordering order )
Теперь давайте сделаем ссылку на Заказ:
void sort( Iterator start, Iterator end, Ordering const& order )
Как насчет этого?
std::function< void(int, int) > alice;
std::function< void(int, int) > bob;
alice = [&]( int x, int y ) { std:swap(alice, bob); return x<y; };
bob = [&]( int x, int y ) { std:swap(alice, bob); return x>y; };
Теперь позвоните sort( begin(vector), end(vector), alice )
.
Каждый раз, когда вызывается <
, упомянутый объект order
меняет свое значение. Теперь это довольно смешно, но когда вы взяли Ordering
на const&
, оптимизатор должен был принять во внимание эту возможность и исключить ее при каждом вызове вашего кода заказа!
Вы бы не стали делать вышеописанное (и на самом деле эта конкретная реализация является UB, поскольку она нарушила бы любые разумные требования к std::sort
); но компилятор должен доказывать, что вы не сделали что-то «такого» (изменить код в ordering
) каждый раз, когда он следует за order
или вызывает его! Это означает постоянную перезагрузку состояния order
или встраивание и доказательство того, что вы не совершали такого безумия.
Делать это, беря по значению, на порядок сложнее (и в основном требуется что-то вроде std::ref
). У оптимизатора есть функциональный объект, он локальный, и его состояние локальное. Все, что хранится в нем, является локальным, и компилятор и оптимизатор знают, кто именно может это модифицировать на законных основаниях.
Каждая написанная вами функция, принимающая const&
, которая когда-либо покидала свою «локальную область» (скажем, называемая библиотечной функцией C), не может предполагать, что состояние const&
осталось прежним после его возвращения. Он должен перезагрузить данные оттуда, куда указывает указатель.
Теперь я сказал передавать по значению, если нет веской причины. И есть много веских причин; ваш тип очень дорого переместить или скопировать, например, это отличная причина. Вы записываете в него данные. Вы на самом деле хотите, чтобы она менялась по мере того, как вы читаете ее каждый раз. И т.п.
Но поведение по умолчанию должно быть передано по значению. Переходите к ссылкам только в том случае, если у вас есть веская причина, потому что затраты распределены и их трудно определить.
person
Yakk - Adam Nevraumont
schedule
12.12.2016
int
и т. д. вместоconst&
. - person Baum mit Augen   schedule 12.12.2016string
s по значению, и это похоже на указатель иsize_t
? Лямбда может быть намного больше, в зависимости от блока захвата. - person Jonathan Mee   schedule 12.12.2016size_t
Однако это не то, что копируется. Копируется массив, на который указывает указатель, и он (потенциально) большой. Лямбда может быть намного больше Да, но обычно это не так. С другой стороны, более простое встраивание является реальным преимуществом. - person Baum mit Augen   schedule 12.12.2016string
, но вы правы, это был плохой пример, нам сказали копировать по ссылке, чтобы предотвратить копирование строки в памяти. - person Jonathan Mee   schedule 12.12.2016