Q: 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:


*

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

*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?

A: 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...
}

