Google’s C ++ Style Guide. Part 6

Part 1. Introduction

Part 5. Functions
Part 6. Specificity of Google

This article is a translation of part of Google’s C ++ style guide into Russian.
Original article (fork on github), updated translation

Google specific

There are various tricks and tools that are used to make C ++ code more robust. And yes, they may be different from what other companies use.

Ownership and smart pointers

Preferably, a dynamically created object has one (dedicated) owner. The transfer of such “ownership” is desirable through smart pointers.

Definition
“Ownership” is an accounting technology used to manage dynamically allocated memory or other resources. The owner of a dynamic entity (object) is an object or function that is responsible for deleting an entity when it is not needed. Ownership can be distributed, in which case it is usually the last remaining owner who is responsible for deleting. Even if ownership is not distributed, this mechanism can be used to transfer ownership from one object (or code) to another.

Smart pointers are classes that function like regular pointers; for example, they overload operators * and ->… Several types of smart pointers can be used to automatically manage ownership: keeping track of owners, deleting objects. std :: unique_ptr it is a smart pointer added in C ++ 11 that implements exclusive ownership (only one owner); the object is removed if the instance goes out of scope std :: unique_ptrstd :: unique_ptr cannot be copied, however it can be transferred (move) to another std :: unique_ptrthat in fact there is a transfer of ownership. std :: shared_ptr it is a smart pointer that implements distributed ownership. std :: shared_ptr can be copied, with ownership shared among all copies. The managed object is deleted when the last copy is destroyed std :: shared_ptr

Per

  • It is very difficult to manage dynamic memory without some kind of ownership accounting mechanism.
  • Transferring ownership can be easier and faster than copying an object. Also, not all objects can be copied.
  • Transferring ownership can be easier than copying a pointer or using links, since there is no need to reconcile the life cycle of an object between different parts of the code.
  • Smart pointers can improve the readability of code, make its logic more understandable, self-documenting, and consistent.
  • Smart pointers can eliminate manual ownership, simplify code, and avoid a lot of bugs.
  • For constant objects, distributed ownership can be a simple and efficient alternative to full copying.

Against

  • Ownership must be represented and passed through pointers (either smart or ordinary). The semantics of pointers are more complicated than working with values, especially in APIs: in addition to ownership, you need to worry about the correctness of the types used (aliasing), lifetime, mutability of objects, etc.
  • The performance costs of copying values ​​are often overestimated, so the performance gains when transferring ownership (versus simple copying) in some cases cannot justify the deterioration in readability and the increase in code complexity.
  • Ownership APIs can impose their own constraints on the memory management model (order).
  • When using smart pointers, there is no clear understanding of exactly where (in the code) the resources will be released.
  • std :: unique_ptr implements transfer of ownership via C ++ 11 move semantics, which is new and can make your code difficult to understand.
  • Distributed ownership, on the one hand, allows for neat ownership management, on the other hand, it can complicate the system architecture.
  • Distributed ownership requires runtime accounting, which can impact performance.
  • In some cases (for example, creating circular references), objects with distributed ownership will never be deleted.
  • Smart pointers cannot always replace regular pointers.

Verdict
If you need to work with dynamic memory, then it is preferable that the code that allocates the memory also owns it. If other code wants to access that memory, then you can pass a copy, pointer, or reference (all without transferring ownership). It is preferable to use std :: unique_ptr to explicitly transfer ownership. For example:

std::unique_ptr<Foo> FooFactory();
void FooConsumer(std::unique_ptr<Foo> ptr);

Don’t design (use) distributed ownership code for no good reason. Alternatively, it may be a desire to avoid a “heavy” copy operation, but be sure to make sure that the gain is substantial and the shared object is immutable (ie.

std :: shared_ptr

). If you need distributed ownership, then use

std :: shared_ptr

Never use

std :: auto_ptr

… As a replacement, there is

std :: unique_ptr

cpplint

To check your code for style errors use

cpplint.py

cpplint.py – a utility that reads a file with a code and detects many style errors. Of course, it is not perfect, sometimes it gives false positive and false negative errors, but it is still a useful utility. False positive errors can be eliminated by inserting // NOLINT at the end of a line of code, or // NOLINTNEXTLINE on the previous line.

Sometimes the project has instructions on where to get it and how to use it. cpplint.py… If your project doesn’t have one, then you can simply download cpplint.py


Notes:

Image taken from

open source

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *