class 成员中 unique_ptr 的正确用法
Correct usage of unique_ptr in class member
我正在尝试真正从 c++98 迁移到 c++11 和更新版本。我已经对大部分新内容了如指掌,但我仍然不确定 unique_ptr
.
的正确用法
考虑下面的示例,其中 class A 有一个 unique_ptr 成员(我以前会使用原始指针!)。当用户需要时,应该通过在其他地方调用函数(不是 class 的一部分)来分配这个成员变量。这是正确的用法吗?如果没有,最好的选择是什么?
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;
}
你的代码工作正常(虽然冗余* move
可以省略)但最好尽早构建 unique_ptr
:
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;
}
这样就很清楚 generateMyType
的 return 值必须由调用者删除,并且内存泄漏的可能性较小(例如,如果 generateMyType
return早)。
* move
是多余的,因为:
- 无法移动原始指针。
- 无论如何,
generateMyType()
表达式的结果已经是一个右值。
Is this the correct usage?
除了 std::move
是多余的,是的,这是正确的。这是多余的,因为 a) 复制裸指针,无论它们是左值还是右值,以及 b) 该函数没有 return 引用,因此 return 值已经是右值,因此不需要转换。
但还有改进的余地。特别是,我建议 return 来自工厂函数的唯一指针:
std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType()
这可以防止 temp
在初始化抛出异常时泄漏,并使工厂用户更难意外泄漏 returned 指针。
为什么不让它成为通用模板工厂?
在header.
template <typename T>
std::unique_ptr<T> generateMyType();
classss A {
private:
std::unique_ptr<MyType> mt;
std::unique_ptr<MyOtherType> mot;
public:
void initStuff() {
mt = generateMyType<MyType>();
mot = generateMyType<MyOtherType>();
}
};
并且在源文件中
template <typename T>
std::unique_ptr<T> generateMyType()
{
auto temp = std::make_unique<T>();
return temp;
}
我正在尝试真正从 c++98 迁移到 c++11 和更新版本。我已经对大部分新内容了如指掌,但我仍然不确定 unique_ptr
.
考虑下面的示例,其中 class A 有一个 unique_ptr 成员(我以前会使用原始指针!)。当用户需要时,应该通过在其他地方调用函数(不是 class 的一部分)来分配这个成员变量。这是正确的用法吗?如果没有,最好的选择是什么?
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;
}
你的代码工作正常(虽然冗余* move
可以省略)但最好尽早构建 unique_ptr
:
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;
}
这样就很清楚 generateMyType
的 return 值必须由调用者删除,并且内存泄漏的可能性较小(例如,如果 generateMyType
return早)。
* move
是多余的,因为:
- 无法移动原始指针。
- 无论如何,
generateMyType()
表达式的结果已经是一个右值。
Is this the correct usage?
除了 std::move
是多余的,是的,这是正确的。这是多余的,因为 a) 复制裸指针,无论它们是左值还是右值,以及 b) 该函数没有 return 引用,因此 return 值已经是右值,因此不需要转换。
但还有改进的余地。特别是,我建议 return 来自工厂函数的唯一指针:
std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType()
这可以防止 temp
在初始化抛出异常时泄漏,并使工厂用户更难意外泄漏 returned 指针。
为什么不让它成为通用模板工厂?
在header.
template <typename T>
std::unique_ptr<T> generateMyType();
classss A {
private:
std::unique_ptr<MyType> mt;
std::unique_ptr<MyOtherType> mot;
public:
void initStuff() {
mt = generateMyType<MyType>();
mot = generateMyType<MyOtherType>();
}
};
并且在源文件中
template <typename T>
std::unique_ptr<T> generateMyType()
{
auto temp = std::make_unique<T>();
return temp;
}