Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use unique_ptr instead of local object?

I'm wondering when we should use unique_ptr (or boost::scope_ptr) instead of local object.

There are two possible cases I can think of:

  1. The object is large that exceed stack size of a thread. But in this case you can always increase size of thread.

  2. Polymorphism. e.g. unique_ptr<C> p; if ... p.reset(new C1); else p.reset(new C2);. But I am not sure when exactly we need this. If this p is a parameter for a function, we can simply say: if ... foo(new C1); else foo(new C2);

Are there any other cases that we should use unique_ptr instead of local object?

like image 216
Deqing Avatar asked Sep 27 '14 06:09

Deqing


People also ask

When should we use unique_ptr?

When to use unique_ptr? Use unique_ptr when you want to have single ownership(Exclusive) of the resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another.

What are the differences between a unique_ptr and a regular pointer?

In short: Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.

What is the class template unique_ptr used for?

The unique_ptr class supersedes auto_ptr , and can be used as an element of C++ Standard Library containers. Use the make_unique helper function to efficiently create new instances of unique_ptr . unique_ptr uniquely manages a resource.

What does unique_ptr get do?

unique_ptr::getReturns a pointer to the managed object or nullptr if no object is owned.


1 Answers

Polymorphism

Polymorphism is a common reason. A typical example is your object is created by a factory that returns a unique_ptr:

std::unique_ptr<C> factoryFunction(int arg) {
  switch (arg) {
    case 1:
      return std::make_unique<C1>();
    case 2:
      return std::make_unique<C2>();
    default:
      return nullptr; 
  }
}

void someFunction(int arg) {
  auto c = factoryFunction(arg);
  if (c) {
    // do something with c...
  }
}

Transfer ownership

In your comment you say you prefer shared_ptr if you need a variable that lives longer than the scope it is declared. I think you should actually prefer unique_ptr. By returning a unique_ptr you are transferring ownership to the caller. Like factoryFunction does above. Or perhaps to return a big expensive-to-move object:

using BigArray = std::array<BigPOD, 1000>;

std::unique_ptr<BigArray> getBig() {
  auto big = std::make_unique<BigArray>();
  // fill big...
  return big;
}

unique_ptr has less overhead than shared_ptr and it makes ownership clearer. I would only use shared_ptr if ownership needs to be shared.

Passing a unique_ptr into a function means you are transferring ownership into the function (a "sink"). For example a constructor:

class Foo {
 private:
  std::unique_ptr<BigArray> array_;
 public:
  Foo(std::unique_ptr<BigArray> array) : array_(std::move(array)) {}
};

void someFunction() {
    auto big = getBig();
    auto foo = Foo(std::move(big));
    // do something with foo...
}
like image 76
Chris Drew Avatar answered Oct 27 '22 10:10

Chris Drew