Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
roth_stephan_clean_c20_sustainable_software_development_patt.pdf
Скачиваний:
29
Добавлен:
27.03.2023
Размер:
7.26 Mб
Скачать

Chapter 4 Basics of Clean C++

The main advantage of using references instead of pointers for arguments is that there’s no need to check that the reference is not a nullptr. The simple reason for this is that references are never "NULL." (Okay, I know that there are some subtle possibilities where you can still end up with a null reference, but these presuppose a very foolish or amateurish programming style.)

And another advantage is that you don’t need to dereference anything inside the function with the help of the dereference operator (*). That will lead to cleaner code. The reference can be used inside the function as it has been created locally on the stack. Of course, if you don’t want to have any side effects, you should make it a const reference (see the upcoming section about const correctness).

If it is inevitable to deal with a pointer to a resource, use a smart one

If you cannot avoid using a pointer because the resource must be created on the heap, you should wrap it immediately and take advantage of the so-called RAII idiom (resource acquisition is initialization).

Customer* customer1 = new Customer(); // Bad! Don’t do that.

auto customer2 = std::make_unique<Customer>(); // Good: the heap-allocated customer is owned by a smart pointer

That means that you should use a smart pointer for it. Since smart pointers and the RAII idiom play an important role in modern C++, there is a section dedicated to this topic in Chapter 5. Always follow rule R.3 from the C++ Core Guidelines [Cppcore21]: A raw pointer (a T*) is non-owning.

If an API returns a raw pointer...

..., well, then we have an “it-depends-problem.”

Pointers are often returned from APIs that are more or less out of our hands. Typical examples are third-party libraries.

In the lucky case that we are confronted with a well-designed API that provides factory methods to create resources and provides methods to hand them back to the library for safe and proper disposal, we have won. In this case we can once again take advantage of the RAII idiom (resource acquisition is initialization; see Chapter 5). We can create a custom smart pointer to wrap the regular pointer, whose allocator and deallocator could handle the managed resource as expected by the third-party library.

111