Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use unique pointer or stack variable as class member?

Tags:

c++

Assume we have two classes A and B. By design, A’s object will be dynamically allocated through make_unique.

The class B will be one of the class member of A. should I use std::unique_ptr of B in A or just define a normal variable of B in A?

class B {};

class A {
  A(std::uniqur_ptr<B> b_ptr) : b_(move(b_ptr)) {}

 private:
  std::unique_ptr<B> b_;
};

or

class B {};

class A {
  A(const B& b) : b_(b) {}

 private:
  B b_;
};

just want to know the difference of above snippets.

like image 351
JoJo Avatar asked Sep 07 '25 04:09

JoJo


1 Answers

As @eerorika said, storing it directly as a member variable is often a better default to go to.

std::unique_ptr is used to denote unique ownership (e.g. the class using this "owns" the memory at that location) -- but ordinarily this is only used when necessary for technical reasons. To name a few such technical reasons:

  • You need polymorphic behavior, but also need your class to own the object. In such a case, you would be using a std::unique_ptr<Base> to use virtual-dispatch to call functions from the underlying Derived instances. You can't store a value of type Base and get polymorphic behavior, so it has to be done indirectly by either a reference or a pointer. std::unique_ptr makes this possible while conveying the ownership semantics.

  • You have a class that is extremely large, or costly to copy/move. For example, if you have a data member of std::array<int,100000> -- you may not want to have to copy that around directly. However, a std::unique_ptr will instead use indirection while allowing for the object to be constructed once and passed in (no penalty for copying)

  • You have a class that is uncopyable and immovable, but you would like to make the owning class copy or movable. For example, you may have a std::mutex internally -- but you may want to permit moving. In such a case you may have either std::unique_ptr<std::mutex> or, better yet, an internal struct held by a unique_ptr so that moving is a cheap and easy operation (since now it only moves pointers).

  • You need the data to outlive the class. Dynamic lifetimes allow lifetimes that are irrespective of scopes, and in some cases, this can be necessary if you want the inner workings of a class to be kept alive outside the normal scope of that class.

There are plenty of reasons where a std::unique_ptr is the "right" choice, but these are the most common ones that come to mind. There is also std::shared_ptr/std::weak_ptr used for sharing, which has similar justifications to above, but matters when ownership needs to be distributed across multiple objects.

In either case, the determination always comes down to the technical reasons/requirements for your class. In your minimal example, class B{} is empty, so it doesn't make sense to use std::unique_ptr here.

like image 111
Human-Compiler Avatar answered Sep 09 '25 23:09

Human-Compiler