необязательные указатели и неконстантные ссылки в C ++

12

В разделе « Другие функции C ++», «Аргументы ссылок » Руководства по стилю Google C ++ , я читал, что неконстантные ссылки не должны использоваться.

Все параметры, передаваемые по ссылке, должны быть помечены как const.

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

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

Неконстантные ссылки действительно так плохи? Запрещено ли это только для Google или это общепринятое правило? Что оправдывает дополнительные усилия для реализации выходных параметров в качестве указателей?

волк
источник
2
«использование указателя для него приводит к пропуску всего тела функции», что?
трещотка урод
@ratchetfreak Я пытался уточнить это. Я признаю, что подобные функции могут показывать некоторые недостатки дизайна. Указатель всегда формально необязателен, поэтому его необходимо проверить перед разыменованием.
Вольф
4
Руководство по стилю Google C ++ довольно задом наперед. По моему субъективному мнению, это должно быть сожжено.
Сиюань Рен
Что касается этого конкретного пункта, я думаю, что обоснование состоит в том, что принуждение программистов писать амперсанд, когда аргументы могут быть видоизменены, показывает более ясное намерение.
Сиюань Рен
4
Руководство по стилю Google было написано для поддержки однородного кода в старых проектах Google. Если вы не работаете над унаследованными проектами (которые были написаны с помощью этого руководства по стилю с самого начала), вам, вероятно, не следует его использовать (оно задает множество правил, которые не подходят для нового кода (c ++ 11, c ++ 14) , c ++ 17)).
utnapistim

Ответы:

18

Логическое обоснование руководства по стилю Google заключается в том, чтобы на сайте вызова функции было ясно, является ли параметр входным параметром или выходным параметром. (См. Здесь для дальнейшего обсуждения.) Другие языки определяют параметры, явно заданные; Например, в C # есть outключевое слово, которое необходимо использовать на сайте вызовов . Поскольку C ++ не делает это явно, Google решил использовать const ref. против указателя, чтобы было понятно.

Это только правило Google? Нет, но я сомневаюсь, что это очень широко распространено. Я не думаю, что видел его вне руководства по стилю Google и групп, которые явно придерживаются частей руководства по стилю Google. (Например, мне понравилась идея, когда я впервые прочитал руководство по стилю Google много лет назад и использовал его для своего собственного кода.)

В частности, недавно объявленные основные принципы C ++ предпочитают возвращаемые значения выходным параметрам (почти) для всего и используют неконстантные ссылки для остальных. Использование Google указателей и ссылок может сделать выходные параметры более понятными, но возвращаемые значения еще яснее. Теперь, когда C ++ 11 имеет стандартизированные перемещения (ссылки на значения, &&чтобы сделать возврат многих типов дешевыми) и кортежи (позволяющие легко возвращать несколько значений), многие из вариантов использования для параметров out больше не применяются.

Основные принципы C ++ имеют несколько громких имен (Bjarne Stroustrup, Herb Sutter), поддерживаются Microsoft и охватывают новейшие функции C ++ (в отличие от руководства по стилю Google), поэтому я ожидаю, что его рекомендации будут более популярными, чем Google.

Джош Келли
источник
Спасибо за ваш ответ (также за краткую экскурсию по C #). Простота рецензирования - это, конечно, важный момент, особенно в проектах с открытым исходным кодом. С дешевыми доходами в современном C ++ эти соображения потеряют свою важность. Со старым унаследованным программным обеспечением и устаревшими компиляторами оно может быть все еще полезным.
Вольф
Я не забыл об этом, но C ++ Core Guidelines не так быстро получить. Интересно, что « Философия» демонстрирует обоснование этих правил, а также модернизированный взгляд на программирование («Выразить идеи непосредственно в коде» читается как Zen of Python) как способ общения.
Вольф
Дополнение: прямая ссылка на раздел «Философия» C ++ Code Guidelines.
Вольф
1

Есть 2 варианта работы с недопустимым указателем, переданным в первую очередь, с первой проверкой и ранним возвратом, или пусть это будет неопределенным поведением (если вам важнее скорость, чем надежность).

Проверка так же проста, как:

void foo(void* buffer){
    if(buffer == nullptr)
        return;

    //actually foo

    // note no increase in indentation required

}

Этот тип проверки обычно принимается как проверка параметров. Если вы видите код, то совершенно очевидно, что вы ожидаете, что ненулевой указатель будет передан и вернется раньше, если нет. Это позволяет вам не беспокоиться о недействительных указателях.

чокнутый урод
источник
Ну, я подумал об этой модели и считаю ее абсолютно разумной. К сожалению, это выглядит не так ясно, как assert(buffer);Зная, что assert активен только для отладочной версии, я иногда хочу иметь rt_assert(buffer);исключение, которое вызывает исключение. Отступы returnвыглядят немного опасно ... Кстати: ваш фрагмент кода - хорошая иллюстрация моего вопроса о указателях для вывода.
Вольф
1

Все сводится к вашему наблюдению If an output parameter is required.

Единственное место, где сигнатура функции должна иметь выходной параметр, - это когда он задан внешним API, и в таком случае вы просто оборачиваете внешний API во что-то, гарантирующее, что всегда есть действительный pointee.

Внутренне вы избегаете выходных параметров, расширяя возвращаемый тип, чтобы он был составным из всех «аутов»

Caleth
источник
Вы имеете в виду единственное место, где я не могу предоставить необязательный указатель? Правда, но я не уверен, The only place where...действительно ли ваше правило применимо ко всем случаям. То, что вы предлагаете, выглядит так: избегайте выходных параметров в функциях ваших собственных программ. Правда для новых программ.
Вольф
1
Да, избегайте выходных параметров, предпочитайте составные типы возврата, отредактированные, чтобы сделать это более ясным
Caleth