9

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?

Deqing
  • 14,098
  • 15
  • 84
  • 131
  • 2
    `unique_ptr` doesn't create a brand new storage duration type. So, your question really is about using the stack vs using the heap. This [answer](http://stackoverflow.com/questions/599308/proper-stack-and-heap-usage-in-c?rq=1) should help. – Pradhan Sep 27 '14 at 06:28
  • Your first reason is a rather esoteric one IMO. An object representing such a huge amount of data will very likely have it allocated internally on the heap anyway (for example, a `std::vector` or a `std::string`). Changing the stack size always has the smell of hacking. YMMV. – Christian Hackl Sep 27 '14 at 10:06
  • @Pradhan I will use heap if I need a variable lives longer than the scope it declared, same as the answer of the link you provided. But in this case I would prefer `shared_ptr`. I still can't see the best situation that suits `unique_ptr`. – Deqing Sep 27 '14 at 10:48

1 Answers1

11

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...
}
Chris Drew
  • 14,926
  • 3
  • 34
  • 54