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;
}
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:
generateMyType()
expression is already an rvalue anyways.Is this the correct usage?
Besides std::move
being redundant, yes this is correct. It is redundant because a) Bare pointers are copied, whether they are lvalues or rvalues and b) The function doesn't return a reference, so the return value is already an rvalue so there is no need to convert.
But there is room for improvement. In particular, I recommend to return a unique pointer from the factory function:
std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType()
This prevents temp
from leaking if the initialization throws an exception, and makes it much harder for the user of the factory to accidentally leak the returned pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With