在unique_ptr上有一个铸造操作员有危险吗?
Is it dangerous to have a cast operator on a unique_ptr?
我们有一个广泛的代码库,目前使用原始指针,我希望迁移到unique_ptr。 但是,许多函数期望原始指针作为参数,在这些情况下不能使用unique_ptr。 我意识到我可以使用 get() 方法来传递原始指针,但这会增加我必须接触的代码行数,而且我觉得它有点难看。 我滚动了自己的unique_ptr如下所示:
template <class T>
class my_unique_ptr: public unique_ptr <T>
{
public:
operator T*() { return get(); };
};
然后,每次我为需要原始指针的函数参数提供my_unique_ptr时,它都会自动将其转换为原始指针。
问题:这样做本身有什么危险吗? 我本以为这将是unique_ptr实现的一部分,所以我假设它的遗漏是故意的 - 有谁知道为什么?
式转换可能会意外发生很多丑陋的事情,例如:
std::unique_ptr<resource> grab_resource()
{return std::unique_ptr<resource>(new resource());}
int main() {
resource* ptr = grab_resource(); //compiles just fine, no problem
ptr->thing(); //except the resource has been deallocated before this line
return 0; //This program has undefined behavior.
}
unique_ptr<>
上调用get
相同,但它会自动完成。 您必须确保在函数返回后未存储/使用指针(因为unique_ptr<>
在其生存期结束时将删除它)。
还要确保不要在原始指针上调用delete
(即使是间接的)。
要确保的另一件事是,您不会创建另一个获取指针所有权的智能指针(例如另一个uniqe_ptr<>
) - 请参阅上面的删除注释
unique_ptr<>
没有自动为您执行转换(并明确调用get()
)的原因是为了确保您可以控制何时访问原始指针(以避免上述可能以静默方式发生的问题)
在unique_ptr
上提供隐式转换运算符(到原始指针)的主要"危险"源于这样一个事实,即unique_ptr
应该对单所有权语义进行建模。 这也是为什么无法复制unique_ptr
,但可以移动它。
考虑一下这种"危险"的例子:
class A {};
/* ... */
unique_ptr<A> a(new A);
A* a2 = a;
unique_ptr<A> a3(a2);
现在,两个unique_ptr
模型 单一所有权语义 在所指向的对象上, 自由世界的命运 - 不,宇宙 - 悬而未决。
好吧,我有点戏剧化,但这就是想法。
就解决方法而言,我通常只会在指针上调用.get()
并完成它,小心地认识到我刚刚got()
的内容缺乏所有权。
鉴于您有一个大型的遗留代码库,您正在尝试使用 unique_ptr
迁移到该代码库,我认为您的转换包装器很好 - 但前提是您和您的同事将来在维护此代码时不会犯错误。 如果这是您认为可能的可能性(我通常会这样做,因为我偏执狂),我会尝试改造所有现有代码以显式调用.get()
,而不是提供隐式转换。 编译器将很乐意为您找到需要进行此更改的所有实例。
在unique_ptr上有一个铸造操作员有危险吗?
已编辑 查看评论
---不,这当然不应该是危险的---:
事实上,该标准要求隐式explicit
转换为"安全布尔"(参见安全布尔习语)。
编辑说明:
新标准(也引入了unique_ptr)引入了explicit operator T()
铸件。它仍然适用于unique_ptr,就好像它是一个隐式转换一样,在那个if
,while
,for(;x;)
自动上下文转换为布尔值。
在我的辩护中,我的知识主要基于像 Boost 这样的 C++03 库,这些库确实定义了向隐式unspecified-bool-type
转换。
我希望这对其他人仍然有帮助。
(有关更多规范处理,包括转换为原始指针,请参阅其他答案)
- 未初始化的变量有什么危险
- 是否有 C++20 浮点数的包装器,使我能够默认宇宙飞船操作员?
- 是否有安全的导航操作员C++?
- 有条件的操作员怪异的输出
- 当直接分配时,为什么此功能指针分配起作用,而不是与有条件的操作员一起使用
- 为什么继承的受保护操作员=()有公共访问权限
- 有条件的操作员从其参数的副本中返回值
- 是否有任何用于ConstexPR操作员 (INT)的应用程序(INT)
- 我无法与操作员>>匹配有什么原因吗?
- 创建虚函数的纯虚函数有危险吗?
- 操作员+过载有什么问题?
- 一次使用#pragma有什么危险
- C STL,我想知道地图中的双向迭代器和操作员[]之间有什么不同
- &lt;&lt;&lt;的这些超载有什么区别操作员
- 这些不同的方式在“ this”上调用操作员有什么区别
- STD ::向量有转换操作员吗?我看到了什么
- 在unique_ptr上有一个铸造操作员有危险吗?
- List Traversal w/temp指针-在声明指针时分配指针引用的节点空间有危险
- 将const char*赋值给string对象有危险吗?
- 在c++中使用嵌套注释来快速(取消)激活代码块是有危险的