#c #reference #pass-by-reference #return-by-reference
#c #ссылка #передача по ссылке #возврат по ссылке
Вопрос:
Возьмем следующий код, где функция возвращает по ссылке:
#include <cstdio>
using namespace std;
int amp; myFunction(int amp; input) {
return input;
}
int main() {
int x;
int y = 10;
x = myFunction(y);
printf("x is %dn",x); // x is 10
printf("y is %dn",y); // y is 10
x = 20;
printf("x is %dn",x); // x is 20
printf("y is %dn",y); // y is 10
return 0;
}
Кроме очевидной ошибки возврата ссылки на локальную переменную функции (что здесь не так), есть ли какие-либо вещи, на которые следует обратить внимание при такой настройке? Другими словами, есть ли в этом коде что-то «больше», чем функция, которая просто возвращает вещи по ссылке, чтобы избежать ненужных операций копирования?
Комментарии:
1. Извините, я этого не заметил. Этот случай в порядке.
2. Нет, больше ничего. На самом деле это часто делается с помощью операторов << и >>
3. » функция, которая просто возвращает вещи по ссылке, чтобы избежать ненужных операций копирования » Так ли это здесь, или вы подразумеваете, что это можно сделать в качестве оптимизации? Потому что обычно это делается для семантики, а не для преждевременной оптимизации.
4. Это нормально и делается в других местах. как @UKMonkey говорит, что сделано с операторами потока. например, здесь: en.cppreference.com/w/cpp/string/basic_string/operator_ltltgtgt
5. этот код похож на стандартный оператор << для std::ostream . так что это обычный способ кодирования
Ответ №1:
Кроме очевидной ошибки возврата ссылки на локальную переменную функции (что здесь не так), есть ли какие-либо вещи, на которые следует обратить внимание при такой настройке?
Нет, не совсем, это совершенно справедливо, но и не имеет никакого преимущества. (в текущем состоянии myFunction
)
чтобы избежать ненужных операций копирования?
Здесь все еще создается копия:
int x;
int y = 10;
x = myFunction(y); // value of y is copied to x.
Это менее читабельно и ничего не ускоряет, когда дело доходит до обычной инициализации:
int x;
int y = 10;
x = y;
В этой ситуации нет причин делать это, просто придерживайтесь обычной инициализации.
Конечно, если myFunction
добавляет какую-то модификацию к более сложному объекту, чем intamp;
тогда, вы можете воспользоваться возвращением ссылки, как только сможете:
chain.method().calls();
Комментарии:
1. Спасибо! Да, конечно, myFunction() бесполезна, как и в моем примере кода. Я просто привел минимальный пример, о котором мы можем поговорить.
Ответ №2:
Предоставленный вами код работает, потому что вы передаете переменную в свою функцию по ссылке и все равно возвращаете ее по ссылке. Это согласованно и работает, но странно. Почему вы возвращаете ту же переменную, которую вы передаете по ссылке? (Я только что вспомнил из комментариев, что это полезно для цепочки в std::ostream, например.)
С другой стороны, если вы передадите эту переменную по значению, у вас будет висячая ссылка, и она не будет работать. Так что это не сработает:
int amp; myFunction(int input) {
return input;
}
На мой взгляд, единственный возврат по ссылке, который я считаю подходящим, — это если вы возвращаете переменную из метода класса. Кроме того, я не думаю, что вам вообще следует возвращать по ссылке.
Вы можете перехватить переменную как постоянную ссылку и избежать ее копирования, если хотите, без зависания, если вы сделаете это:
int myFunction(int input) {
return input;
}
int main()
{
const intamp; myInt = myFunction();
//myInt is still valid here
}
Это особый случай, который.
Комментарии:
1. Я имею в виду, что первая часть выполняется в самом stl. и о передаче по значению. В вопросе указано, что OP знает об этом.
2. Спасибо, я спрашиваю об этом конкретном случае (т. Е. Мы не ошибочно возвращаем ссылку на локальную переменную). Есть ли что-нибудь «еще» в этом сценарии?
3. @space_voyager Я не понимаю, зачем тебе это делать. Очень неоднозначно и нечитаемо передавать по ссылке и возвращать одну и ту же переменную по ссылке…
4. @TheQuantumPhysicist это прекрасно читается; фактически это УЛУЧШАЕТ читаемость! Давайте посмотрим на cout << foo << bar << baz ; как вы думаете, << возвращается для использования таким образом? Это также делается в шаблоне builder. foo().SetActive().setBaz()
5. @UKMonkey Ну, ты прав. Это полезно и для цепочки. Я забыл об этом.