Руководство Google по стилю в C++. Часть 6

Часть 1. Вступление

Часть 5. Функции
Часть 6. Специфика Google
Часть 7. Ещё возможности C++




Эта статья является переводом части руководства Google по стилю в C++ на русский язык.
Исходная статья (fork на github), обновляемый перевод.

Специфика Google


Есть различные трюки и средства, которые используются чтобы сделать код на C++ более надёжным. И да, они могут отличаться от того, что используют в других компаниях.

Владение и умные указатели


Предпочтительно, чтобы динамически созданный объект имел одного (выделенного) владельца. Передачу такого «владения» желательно проводить через умные указатели.

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

«Умные» указатели это классы, которые функционируют как обычные указатели; например, в них перегружены операторы * и ->. Некоторые типы умных указателей можно использовать для автоматического управления «владением»: учёт владельцев, удаление объектов. std::unique_ptr это умный указатель, добавленный в C++11, который реализует эксклюзивное владение (только один владелец); объект удаляется в случае выхода из области видимости экземпляра std::unique_ptr. std::unique_ptr не может быть скопирован, однако его можно передать (move) другому std::unique_ptr, что фактически есть передача владения. std::shared_ptr это умный указатель, реализующий распределённое владение. std::shared_ptr можно копировать, при этом владение распределяется между всеми копиями. Управляемый объект удаляется, когда разрушается последняя копия std::shared_ptr.

За


Против


Вердикт
Если необходима работа с динамической памятью, то предпочтительно чтобы код, выделяющий память, ею же и владел. Если другой код хочет получить доступ к этой памяти, то можно передать копию, указатель или ссылку (и всё это без передачи владения). Предпочтительно использовать std::unique_ptr для явной передачи владения. Например:
std::unique_ptr<Foo> FooFactory();
void FooConsumer(std::unique_ptr<Foo> ptr);

Без существенной причины не проектируйте (не используйте) код с распределённым владением. Как вариант, это может быть желание избежать «тяжелой» операции копирования, однако обязательно убедитесь, что выигрыш будет существенным и разделяемый объект — неизменяемый (т.е. std::shared_ptr<const Foo>). Если же требуется именно распределённое владение, то используйте std::shared_ptr.
Никогда не используйте std::auto_ptr. В качестве замены есть std::unique_ptr.

cpplint


Для проверки кода на ошибки стиля используйте cpplint.py.

cpplint.py — утилита, которая читает файл с кодом и определяет многие ошибки в стиле. Конечно, она не идеальна, иногда выдаёт ложно-положительные и ложно-отрицательные ошибки, однако это всё равно полезная утилита. Ложно-положительные ошибки можно исключить, если вставлять // NOLINT в конце строчки кода или // NOLINTNEXTLINE на предыдущей строке.


Иногда в проекте есть инструкция, откуда брать и как пользоваться cpplint.py. Если в вашем проекте такой нет, то можно просто скачать cpplint.py.





Примечания:
Изображение взято из открытого источника.
@Apoheliy
20.10.2021 23:39 UTC
Первоисточник

Комментарии

@oleg-m1973
20.10.2021 20:09 UTC
0

Обычно вердикт, это компромисс между аргументами "за" и аргументами "против". Т.е. он должен отвечать на вопрос - почему так, а не иначе. А здесь - вердикт (худо-бедно верный) сам по себе, аргументы сами по себе.

Ещё раз скажу, что нужно учитывать, что Гугл - это гигантская корпорация, которая может позволить себе программировать в плохом стиле.

@DarkEld3r
21.10.2021 09:28 UTC
0
Гугл — это гигантская корпорация, которая может позволить себе программировать в плохом стиле.

Предположим, но зачем им это делать? Разве должно быть не наоборот? В смысле, если "хороший стиль" даёт выигрыш в 1% (для примера и не важно чего именно: скорости, поддерживаемости или чего-то ещё), то на объёмах гугла разве это не будет куда более заметно, чем в мелком стартапе?

21.10.2021 16:58 UTC
0

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

21.10.2021 21:00 UTC
0
что не так просто, как кажется

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

@DistortNeo
20.10.2021 20:27 UTC
+2
std::unique_ptr реализует передачу владения через семантику перемещения C++11, которая является новой и может затруднить понимание кода.

А ничего, что с момента введения семантики перемещения прошло уже больше 10 лет?

@tzlom
21.10.2021 06:16 UTC
+1

Реалии таковы что 80% разработчиков на C++ с 3 годами коммерческого опыта (не институт) не могут написать шаблон использующий SFINAE (хотя и в курсе что такое существует) и будут избегать самописных шаблонов в принципе, обычно с аргументацией о поддерживаемости другими людьми. Прошло уже больше 20 лет.

21.10.2021 08:42 UTC
0

А я попросту откажусь писать шаблон с SFINAE. Максимум согласен на std::enable_if, но не более того. Считаю, что это крайне неудобный и плохо читаемый костыль, для которого есть хорошие альтернативы в виде constexpr и концептов.

21.10.2021 17:05 UTC
0

Если в организации перешли на C++17, то несомненно. А если готовы на C++20, то можно и на концепты посмотреть.