В веб-приложении каждая задача выполняется в виде запроса и ответа.
Программирование на стороне клиента - это HTML-код с Java-скриптом и его фреймворками, библиотеки выполняются в Internet Explorer, Mozilla, Chrome-браузерах. В сценарии Java-сценария серверные сервлеты программирования выполняются в Tomcat, web-логике, j боссе, WebSphere severs
Обычно рекомендуется использовать наилучшую практику1 для использования pass by const ref для всех типов , за исключением встроенных типов (char
, int
, double
и т. д.), для итераторы и объекты функций (lambdas, классы, полученные из std::*_function
).
Это было особенно верно до существования семантики перемещения . Причина проста: если вы прошли по значению, нужно было скопировать объект и, за исключением очень маленьких объектов, это всегда дороже, чем передача ссылки.
С C ++ 11 , мы получили семантику перемещения . В двух словах, перемещение семантики допускает, что в некоторых случаях объект может передаваться «по значению» без его копирования. В частности, это тот случай, когда объект, который вы проходите, является rvalue .
Само по себе перемещение объекта по-прежнему не менее дорого, чем передача по ссылке. Однако во многих случаях функция будет внутренне копировать объект в любом случае, т. Е. Будет принимать право собственности аргумента.2
. В этих ситуациях мы имеем следующие (упрощенные) off:
«Pass by value» по-прежнему вызывает копирование объекта, если объект не является rvalue. В случае rvalue объект может быть перемещен вместо этого, так что второй случай внезапно перестает «копировать, а затем перемещать», а «перемещать», затем (потенциально) перемещаться снова ».
Для больших объекты, которые реализуют правильные конструкторы перемещения (такие как векторы, строки ...), второй случай - это значительно , более эффективный, чем первый. Поэтому рекомендуется использовать pass by value, если функция переходит в собственность аргумента, и если тип объекта поддерживает эффективное перемещение.
Историческое примечание:
In факт, любой современный компилятор должен уметь вычислять при прохождении по стоимости дорого и неявно конвертировать вызов, чтобы использовать константу ref, если это возможно.
Теоретически. На практике , компиляторы не всегда могут изменить это, не нарушая бинарный интерфейс функции. В некоторых особых случаях (когда функция встроена) копия действительно будет устранена, если компилятор может понять, что исходный объект не будет изменен посредством действий в функции.
Но в целом компилятор не может это определить, и появление семантики перемещения в C ++ делает эту оптимизацию менее актуальной.
1 Например в Scott Meyers, Эффективный C ++ .
2 Это особенно часто относится к конструкторам объектов, которые могут принимать аргументы и хранить их внутри себя, чтобы быть частью состояния построенного объекта.
Изменить: Новая статья Дейва Абрахама на 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 */
}
__restrict__
(который также может работать над ссылками), чем избыточные копии. Слишком плохой стандарт C ++ не использовал ключевое слово C99 restrict
.
– Ruslan
9 July 2017 в 07:31
Простая разность: - В функции у нас есть входной и выходной параметр, поэтому, если ваш параметр ввода и вывода одинаковый, тогда используйте вызов по ссылке else, если параметр ввода и вывода отличается, тогда лучше использовать вызов по значению.
пример void amount(int account , int deposit , int total )
входной параметр: учетная запись, параметр выходного выхода: общий
вход и выход - другой вызов использования vaule
void amount(int total , int deposit )
общий суммарный вывод депозита
Похоже, вы получили свой ответ. Передача по стоимости дорогая, но дает вам копию для работы, если вам это нужно.
Пропустить по значению для малых типов.
Пропустить ссылки const для больших типов (определение большого может варьироваться между машинами). НО, в C ++ 11, переходите по значению, если вы собираетесь потребляйте данные, так как вы можете использовать семантику перемещения. Например:
class Person {
public:
Person(std::string name) : name_(std::move(name)) {}
private:
std::string name_;
};
Теперь вызывающий код будет делать:
Person p(std::string("Albert"));
И только один объект будет создан и перемещен непосредственно в член name_
в классе Person
, Если вы перейдете по ссылке const, необходимо будет скопировать его в name_
.
Зависит от типа. Вы добавляете небольшие накладные расходы, чтобы сделать ссылку и разыменовать. Для типов с размером, равным или меньшим, чем указатели, использующие копию ctor по умолчанию, вероятно, быстрее перейти по значению.
Это то, что я обычно работаю при разработке интерфейса функции без шаблона:
Как правило, значение для типов некласса и константа ссылки для классов. Если класс действительно маленький, то, вероятно, лучше пройти по значению, но разница минимальна. То, что вы действительно хотите избежать, это передать некоторый гигантский класс по стоимости и все его дублировать - это будет иметь огромное значение, если вы передаете, скажем, std :: vector с довольно несколькими элементами в нем.
std::vector
фактически выделяет свои элементы в куче, и сам векторный объект никогда не растет. Подожди. Если операция приводит к созданию копии вектора, тем не менее, он фактически переместит и дублирует все элементы. Это было бы плохо.
– Steven Lu
26 January 2012 в 00:55
sizeof(std::vector<int>)
является постоянным, но передача его значением по-прежнему будет копировать содержимое в отсутствие умения компилятора.
– Peter
31 January 2012 в 11:56
Как правило, переключение по ссылке const лучше. Но если вам нужно изменить аргумент функции локально, вам лучше использовать передачу по значению. Для некоторых базовых типов производительность в целом одинакова как для передачи по значению, так и по ссылке. Фактически ссылка внутренне представлена указателем, поэтому вы можете ожидать, например, что для указателя обе прохождение одинаковое с точки зрения производительности, или даже передача по значению может быть быстрее из-за ненужного разыменования.
Как было указано, это зависит от типа. Для встроенных типов данных лучше всего перейти по значению.
Вот пример, предположим, что у вас есть целочисленное значение, и вы хотите передать его другой процедуре. Если это значение было оптимизировано для хранения в регистре, то, если вы хотите передать его ссылкой, оно сначала должно быть сохранено в памяти, а затем указателем на эту память, помещенную в стек для выполнения вызова. Если он передается по значению, все, что требуется, - это регистр, вставленный в стек. (Подробности немного сложнее, чем при использовании разных систем вызова и процессоров).
Если вы занимаетесь программированием шаблонов, вы обычно вынуждены всегда передавать const ref, поскольку вы не знаете типов Передача штрафов за передачу чего-то плохого по значению намного хуже, чем штрафы за прохождение встроенного типа по const ref.