Search code examples
c++c++11c++14unique-ptr

Correct usage of unique_ptr in class member


I am trying to really move from c++98 to c++11 and newer. I have wrapped my head over most of the new stuff but I am still not sure about the correct usage of unique_ptr.

Consider the example below, where class A has a unique_ptr member (I would have used raw pointer before!). This member variable should be assigned, when user needs, by calling a function somewhere else (not part of the class). Is this the correct usage? If not, what is the best alternative?

class A {
private:
   unique_ptr<MyType> mt;
public:
   void initStuff() {
      mt.reset(std::move(StaticFuncSomewhereElese::generateMyType()));
   } 
};

MyType* StaticFuncSomewhereElese::generateMyType() {
    MyType* temp = new MyType(...);
    //do stuff to temp (read file or something...)
    return temp;
}

Solution

  • Your code works fine (although the redundant* move can be omitted) but it would be better to construct the unique_ptr as early as possible:

    class A {
    private:
       std::unique_ptr<MyType> mt;
    public:
       void initStuff() {
          mt = StaticFuncSomewhereElese::generateMyType();
       } 
    };
    
    std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType() {
        auto temp = std::make_unique<MyType>(…);
        // `make_unique` is C++14 (although trivially implementable in C++11).
        // Here's an alternative without `make_unique`:
        // std::unique_ptr<MyType> temp(new MyType(…));
    
        //do stuff to temp (read file or something...)
        return temp;
    }
    

    This way it is clear that the return value of generateMyType must be deleted by the caller, and there's less possibility for memory leaks (e.g. if generateMyType returns early).

    * The move is redundant because:

    1. Raw pointers can't be moved.
    2. The result of the generateMyType() expression is already an rvalue anyways.