Dominic,

Thank you for brining this up! Instead of making a decision based on high
level design and coding philosophy, I would really love to see some
concrete examples in our code base where we can start to use unique_ptr and
why it's better. Thoughts?

- Jie

On Wed, Dec 10, 2014 at 3:20 PM, Dominic Hamon <[email protected]>
wrote:

> Hello!
>
> We have access to std::unique_ptr, as many of you know, but we're not using
> it. I'd like to start using it. Before we do, I'd like to discuss how we
> use it, when we use it, and things to be aware of.
>
> The style guide has the following to say (long quote, sorry):
>
> "
> Prefer to have single, fixed owners for dynamically allocated objects.
> Prefer to transfer ownership with smart pointers.
>
> "Ownership" is a bookkeeping technique for managing dynamically allocated
> memory (and other resources). The owner of a dynamically allocated object
> is an object or function that is responsible for ensuring that it is
> deleted when no longer needed. Ownership can sometimes be shared, in which
> case the last owner is typically responsible for deleting it. Even when
> ownership is not shared, it can be transferred from one piece of code to
> another.
>
> "Smart" pointers are classes that act like pointers, e.g. by overloading
> the * and -> operators. Some smart pointer types can be used to automate
> ownership bookkeeping, to ensure these responsibilities are met.
> std::unique_ptr is a smart pointer type introduced in C++11, which
> expresses exclusive ownership of a dynamically allocated object; the object
> is deleted when the std::unique_ptr goes out of scope. It cannot be copied,
> but can be moved to represent ownership transfer. std::shared_ptr is a
> smart pointer type that expresses shared ownership of a dynamically
> allocated object. std::shared_ptrs can be copied; ownership of the object
> is shared among all copies, and the object is deleted when the last
> std::shared_ptr is destroyed.
>
> It's virtually impossible to manage dynamically allocated memory without
> some sort of ownership logic.
> Transferring ownership of an object can be cheaper than copying it (if
> copying it is even possible).
> Transferring ownership can be simpler than 'borrowing' a pointer or
> reference, because it reduces the need to coordinate the lifetime of the
> object between the two users.
> Smart pointers can improve readability by making ownership logic explicit,
> self-documenting, and unambiguous.
> Smart pointers can eliminate manual ownership bookkeeping, simplifying the
> code and ruling out large classes of errors.
> For const objects, shared ownership can be a simple and efficient
> alternative to deep copying.
> Ownership must be represented and transferred via pointers (whether smart
> or plain). Pointer semantics are more complicated than value semantics,
> especially in APIs: you have to worry not just about ownership, but also
> aliasing, lifetime, and mutability, among other issues.
> The performance costs of value semantics are often overestimated, so the
> performance benefits of ownership transfer might not justify the
> readability and complexity costs.
> APIs that transfer ownership force their clients into a single memory
> management model.
> Code using smart pointers is less explicit about where the resource
> releases take place.
> std::unique_ptr expresses ownership transfer using C++11's move semantics,
> which are relatively new and may confuse some programmers.
> Shared ownership can be a tempting alternative to careful ownership design,
> obfuscating the design of a system.
> Shared ownership requires explicit bookkeeping at run-time, which can be
> costly.
> In some cases (e.g. cyclic references), objects with shared ownership may
> never be deleted.
> Smart pointers are not perfect substitutes for plain pointers.
> If dynamic allocation is necessary, prefer to keep ownership with the code
> that allocated it. If other code needs access to the object, consider
> passing it a copy, or passing a pointer or reference without transferring
> ownership. Prefer to use std::unique_ptr to make ownership transfer
> explicit. For example:
>
> std::unique_ptr<Foo> FooFactory();
> void FooConsumer(std::unique_ptr<Foo> ptr);
> Do not design your code to use shared ownership without a very good reason.
> One such reason is to avoid expensive copy operations, but you should only
> do this if the performance benefits are significant, and the underlying
> object is immutable (i.e. std::shared_ptr<const Foo>). If you do use shared
> ownership, prefer to use std::shared_ptr.
>
> Do not use scoped_ptr in new code unless you need to be compatible with
> older versions of C++. Never use std::auto_ptr. Instead, use
> std::unique_ptr.
> "
>
> Now I'm a big fan of explicit ownership and moving ownership rather than
> sharing non-smart pointers, but I recognise that in our code-base,
> ownership is difficult to reason about in many cases. However, we do have
> quite a few cases where we manage lifetime scope with explicit delete calls
> and I'd like to start by eliminating those. Ie, using std::unique_ptr to
> manage lifetime not necessarily ownership.
>
> This is difficult though as we may pass these pointers to other methods or
> even other libprocess processes. In cases that we can reason about the
> lifetime of the various pointers, that should be fine, but we have to be
> careful.
>
> One option is to start by replacing these pointers with process::Owned. The
> downside to this approach is that it introduces more non-standard types
> and, because Owned is implemented using std::shared_ptr, doesn't move us
> closer to defining clear ownership.
>
> ​So the floor is open. Do we:
>
> 1) embrace std::unique_ptr, eliminate raw pointers except in rare,
> well-defined cases from a lifetime point of view?
> 2) eliminate raw pointers in favour of std::shared_ptr and std::unique_ptr
> then work to eliminate the std::shared_ptrs
> 3) use process::Owned everywhere and then find places where we can
> transition them to std::unique_ptr
> 4) do nothing; there's no great benefit to std::unique_ptr and this smart
> pointer thing is just a fad.
>
>
> - dominic​
>
>
> --
> Dominic Hamon | @mrdo | Twitter
> *There are no bad ideas; only good ideas that go horribly wrong.*
>

Reply via email to