2014-10-18 9 views
8

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

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

И далее:

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

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

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

но если

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

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

+2

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

+5

Просто потому, что он от Google не означает, что он должен иметь смысл. –

+0

FWIW, [Titus's CppCon talk] (https://www.youtube.com/watch?v=NOCElcMcFik) – chris

ответ

23

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

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

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

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

5

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

void foo(int a, Bar* b); 

Если b аргумент не является обязательным, или нет необходимости иногда, вы можете вызвать функцию как так

foo(5, nullptr); 

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

void foo(int a, Bar& b); 

Th ru нет пути к не пройти в Bar.

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

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

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

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

Титус, казалось, больше склонялся к колл-сайту, показывая, что все, что было передано, может быть изменено в его видео CppCon. – chris

+0

Благодарим вас за объяснения: я понимаю, что это «отлично и разумно» для выходных аргументов. Но как насчет аргументов ввода-вывода? Я думал, что более опасно использовать указатели вместо ссылок на них! – suizokukan

+0

@suizokukan, ничего, что вы сказали в своем вопросе, не указывает указатели на входные параметры. – chris

1

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

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

4

Вы первый вопрос: «Так, что точка в всегда требует указателя, если я хочу, чтобы избежать указателя быть 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 упрощает код.