Вопрос по объявлению функций - PullRequest
0 голосов
/ 30 августа 2010

Учитывая два примера кода, который является предпочтительным?В первом возвращаемая переменная определяется как локальная переменная.Во втором возвращаемая переменная передается вызывающей стороной.Разрешено ли вам определять функцию и возвращать переменную, которая была ей передана?Я это просто предпочтение одного или другого?есть ли разница в производительности?

float compute_diam(float circumference, float pi) {

float rval;

/* Circumference = pi * diameter, so
   diameter = circumference / pi */

rval = circumference / pi;

return rval;
}

и

float compute_diam(float circumference, float pi, float rval) {

/* Circumference = pi * diameter, so
   diameter = circumference / pi */

rval = circumference / pi;

return rval;
}

Спасибо

Ответы [ 5 ]

3 голосов
/ 30 августа 2010

Я думаю, что в этих двух случаях первый лучше по следующей причине 1. Из-за производительности, когда вы передаете переменную по значению, она создается один раз, когда вы объявляете rval, и однажды, когда вы передаете этот rval в функцию со значением первого rval, скопированного во второе.

Вместо этого, если вы хотите передать переменную таким образом, передайте ее по ссылке как

void main()
{
float result;
compute_diam(2.1, 3.14, &result);
 } 
void compute_diam(float circumference, float pi, float* rval) {

/* Circumference = pi * diameter, so
   diameter = circumference / pi */

*rval = circumference / pi;


}

после завершения функции переменной результат будет содержать значение диаметра.

0 голосов
/ 30 августа 2010

Как правило, единственными причинами сохранения возвращаемого значения по адресу, переданному в качестве параметра, являются:

  • Вам необходимо вернуть несколько значений.
  • Вам необходимо вернуть структуру.
  • Вам необходимо использовать возвращаемое значение функции для возврата ошибок.
  • Функция предназначена для изменения одного из параметров.

Если вы посмотрите стандартную библиотеку C или почти любой API, вы найдете несколько экземпляров возвращаемых значений, хранящихся по адресу, переданному в качестве параметра.

0 голосов
/ 30 августа 2010

Иногда вам может понадобиться передать ссылку на переменную и затем заполнить ее соответствующими значениями или кодами возврата.

Однако второе определение не имеет никакого смысла.

int foo()
{
int a=6;
return a; // This is ok
}

int foo(int a)
{
a = 5;
return a; // Calling function cant access the value 5 in the parameter 
//passed, it has to hold it in another variable
}

void foo(int* a)
{
*a=5;
return; // Here you can return and still access the value 5 in the calling 
//function with the variable passed to it
}

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

0 голосов
/ 30 августа 2010

Это позволяет мне думать, что вы не понимаете, что такое возвращаемое значение или как аргументы передаются функции.

Во втором примере вы не будете изменять rval, который вы даетепри вызове функции, но ее копия.И тогда вы вернете значение rval.

Тогда ваш второй пример "неправильный" (с логической точки зрения).

То, что вы пытались сделать, это

void compute_diam(float circumference, float pi, float& rval) {

/* Circumference = pi * diameter, so
diameter = circumference / pi */

rval = circumference / pi;

}

Редактировать: Исправление, выше только C ++, в C вы должны сделать следующее

void compute_diam(float circumference, float pi, float* rval) {

/* Circumference = pi * diameter, so
diameter = circumference / pi */

*rval = circumference / pi;

}

Где rval дано по ссылке и гдефункция ничего не возвращает (void).

Но в этом простом случае этого следует избегать, интерфейс более понятен, если функция возвращает значение.

Редактировать: Чтобы убедить вас в том, что ваш второй пример плохо сформирован, подумайте о следующем:

float my_result = compute_diam (2.0, 3.14, «почему и что бы я здесь указывал?

0 голосов
/ 30 августа 2010

Я бы предпочел первое, так как второе не имеет никакого смысла. Во-вторых, вы не передаете ссылку или указатель на rval, поэтому вы просто присваиваете локальную переменную (как в первой, но она создается по-другому), а затем возвращаете копию этой переменной вызывающей стороне. , Обратите внимание, что вы не сохраняете значение в rval, переданном в функцию, вы сохраняете его в локальном rval, созданном функцией через список параметров.

Даже если во втором примере передается ссылка на rval, я бы все же предпочел первый, поскольку rval является обычным типом и легко и эффективно копируется. Я также нахожу:

float diameter = compute_diam(circumference, pi);

гораздо более читабельно и кратко, чем:

float diameter = 0;
compute_diam(circumference, pi, diameter);

Если вы помещаете данные в большой объект / структуру, тогда передача ссылки в функцию будет иметь больше смысла. Компилятор много раз может оптимизировать копию, связанную с функцией, которая создает копию для возвращаемого значения, поэтому я, вероятно, останусь с опцией 1, пока вы не обнаружите с помощью профилировщика, что его нужно оптимизировать до чего-то вроде 2-го версия.

Кроме того, вы можете удалить pi из списка аргументов и сделать static const float PI = 3.14xxxx; внутри тела функции.

...