在unique_ptr上使用强制转换操作符是危险的吗?

时间:2012-06-21 20:38:17

标签: c++ c++11 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(); };
};

然后每当我向一个需要原始指针的函数parm提供my_unique_ptr时,它会自动将其转换为原始指针。

问题:这样做有什么本质上的危险吗?我原本以为这将是unique_ptr实现的一部分,所以我认为它的遗漏是故意的 - 有谁知道为什么?

4 个答案:

答案 0 :(得分:7)

有很多丑陋的事情可能会因隐式转换而发生,例如:

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

答案 1 :(得分:4)

与在get上调用unique_ptr<>相同,但会自动完成。在函数返回后,您必须确保指针未被存储/使用(因为unique_ptr<>将在其生命周期结束时将其删除)。

还要确保不要在原始指针上调用delete(甚至间接)。

另一件要确保的是你不创建另一个获取指针所有权的智能指针(例如另一个uniqe_ptr<>) - 请参阅上面的删除注释

unique_ptr<>没有自动为您进行转换(并且您明确调用get())的原因是为了确保您可以控制何时访问原始指针(以避免上述问题可能会无声地发生,否则)

答案 2 :(得分:2)

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(),而不是提供隐式转换。编译器将很乐意为您找到需要进行此更改的所有实例。

答案 3 :(得分:1)

  

在unique_ptr上使用强制转换操作符是危险的吗?

已修改查看评论

---不,它当然不应该是危险的--- 实际上标准要求隐式 {{1}转换为'safe bool'(请参阅Safe Bool Idiom)。

编辑说明:

新标准(也引入unique_ptr)引入了 explicit 强制转型。它仍适用于unique_ptr ,就像它是隐式转换一样,explicit operator T()ifwhile执行自动上下文转换布尔。

在我的辩护中,我的知识主要基于像Boost这样的C ++ 03库,其中定义转换为for(;x;) 隐式

我希望这对其他人来说仍然有用。


(有关更多规范处理的其他答案,包括转换为原始指针)