Руководство по стилю Google о параметрах ввода / вывода в качестве указателей

Руководство по стилю Google C ++ проводит четкое различие (строго следуют cpplint.py) между входными параметрами (→ const ref, value) и параметрами ввода-вывода или вывода (→ неконстантные указатели):

Параметры функций C / C ++ либо вводятся в функцию, либо выводятся
из функции, или оба. Входными параметрами обычно являются значения или
константные ссылки, в то время как выходные и входные / выходные параметры будут
неконстантные указатели.

И далее :

На самом деле в коде Google очень строго принято, что входные аргументы являются значениями или константными ссылками, а выходные аргументы являются указателями.

Но я не могу понять, почему входные / выходные аргументы (я оставляю выходные аргументы в стороне) не должны передаваться по ссылке. В stackoverflow существует множество тем, связанных с этим вопросом: например, Вот, В принятом ответе четко сказано, что

это в основном о стиле

но если

Вы хотите, чтобы иметь возможность передавать нуль, вы должны использовать указатель

Итак, какой смысл всегда требовать указатель, если я хочу, чтобы указатель был нулевым? Зачем использовать ссылки только для входных аргументов?

10

Решение

Причина требования, чтобы выходные параметры передавались как указатели, проста:

Это проясняет на сайте вызова что аргумент потенциально будет видоизменяться:

foo(x, y);     // x and y won't be mutated
bar(x, &y);    // y may be mutated

Когда кодовая база развивается и подвергается постепенным изменениям, которые проверяются людьми, которые могут не знать весь контекст все время, важно уметь как можно быстрее понять контекст и влияние изменений. Таким образом, с этим стилевым правилом сразу становится ясно, вносит ли изменение мутацию.

26

Другие решения

Смысл, который они делают (с чем я не согласен), заключается в том, что у меня есть какая-то функция

void foo(int a, Bar* b);

Если b Аргумент необязательный, или иногда он не нужен. Вы можете вызвать функцию следующим образом:

foo(5, nullptr);

Если функция была объявлена ​​как

void foo(int a, Bar& b);

Тогда нет возможности не пройти в Bar,

Этот момент (акцент мой) полностью основан на мнении и на усмотрение разработчика.

На самом деле в коде Google очень строго принято, что входные аргументы являются значениями или константными ссылками. в то время как выходные аргументы являются указателями.

Если я собираюсь b чтобы быть выходным параметром, любое из следующего является совершенно допустимым и разумным.

void foo(int a, Bar* b);  // The version Google suggests
void foo(int a, Bar& b);  // Reference version, also perfectly fine.
6

Вы первый вопрос: «Так какой смысл всегда требовать указатель, если я хочу, чтобы указатель был null

Использование указателя сообщает вызывающей стороне, что их переменная может быть изменена. Если я звоню foo(bar), является bar будет изменен? Если я звоню foo(&bar) Понятно, что ценность bar может быть изменено
Есть много примеров функций, которые принимают null указывающий необязательный выходной параметр (от макушки головы) time хороший пример.)

Ваш второй вопрос: «Зачем использовать ссылки только для входных аргументов?»

Работать со ссылочным параметром проще, чем с аргументом указателя.

int foo(const int* input){
int return = *input;

while(*input < 100){
return *= *input;
(*input)++;
}
}

Этот код, переписанный со ссылкой, выглядит так:

int foo(const int& input){
int return = input;

while(input < 100){
return *= input;
input++;
}
}

Вы можете увидеть, что с помощью const int& input упрощает код

4

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

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

1