Разъяснения относительно передачи аргументов по ссылке - PullRequest
0 голосов
/ 16 января 2019

Читая о передаче ссылок на функцию в качестве параметров, я обнаружил, что эта статья передает аргументы по ссылке (и код, о котором идет речь), в котором говорится, что:

void getSinCos(double degrees, double &sinOut, double &cosOut)
{
   //SOME PROCESSING WITH THE PARAMETERS
}

Вызывающий должен передать аргументы для хранения обновленных выходных данных, даже если он не намерен их использовать. Что еще более важно, синтаксис немного неестественен, и входные и выходные параметры объединяются в вызове функции. Со стороны вызывающего не очевидно, что sin и cos являются параметрами и будут изменены. Это, вероятно, самая опасная часть этого метода (так как это может привести к ошибкам). Некоторые программисты и компании считают, что это достаточно большая проблема, чтобы рекомендовать не передавать по ссылке таким образом, а вместо этого использовать передачу по адресу при смешивании входных и выходных параметров (который имеет более четкий синтаксис, указывающий, является ли параметр изменяемым или нет).

Конечно, мы не можем передавать временные значения, такие как аргумент 3 или какой-либо другой целочисленный / двойной литерал, когда заданные параметры являются неконстантной ссылкой, но как можно изменить входную переменную и восстановить выходной в той же переменной (так как изменения вносятся в исходную переменную) будет проблематично, как указывает эта статья? Может кто-нибудь, пожалуйста, направьте меня, поскольку я новичок в C ++.

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Эта статья ничего не говорит о «изменении входной переменной и восстановлении вывода в той же самой переменной» говорит только о том, что не очевидно, какие аргументы могут быть изменены при вызове функции :

int x{};
int y{};
foo(x, y); // can you guess which variable has changed?

Часть о передаче по адресу, имеющая «более четкий синтаксис, указывающий, является ли параметр изменяемым или нет», является полной фигней. Он не только страдает от той же проблемы, что и передача по ссылке, но также подразумевает, что некоторые аргументы могут быть необязательными и возможная передача права собственности

int x{};
int y{};
foo(&x, &y); // can you guess which variable has changed?
foo(nullptr, &y); // can you guess whether this is correct usage?
foo(&x, &y); // can you be sure that foo won't delete pointer to x?

Чтобы быть в безопасности, можно использовать что-то вроде явной ссылки (const):

int x{};
int y{};
foo(::std::as_const(x), y); // alright, x should not be changed inside
0 голосов
/ 16 января 2019

Это то, чего люди просто не могут ожидать. Предположим, у вас есть этот код:

int x = 5;
foobar(x);

Какое значение x после вызова функции? Большинство людей ожидают, что оно все равно будет 5, поскольку, за исключением неопределенного поведения, оно не может измениться при передаче по значению. В C даже нет передачи по ссылке, поэтому значение всегда будет 5. Теперь в C ++ внезапно происходит передача по ссылке, и только из этого фрагмента кода вы не можете знать, изменится ли x после вызова функции. Для этого вам нужно взглянуть на фактическую подпись foobar.

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

Сравните это со следующим фрагментом отсюда , объясняющим проход по ссылке, как это происходит в C #:

void Method(ref int refArgument)
{
    refArgument = refArgument + 44;
}

int number = 1;
Method(ref number);
Console.WriteLine(number);
// Output: 45

Здесь вы сразу видите, что оно передается по ссылке, потому что там написано ref number.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...