2012-06-21 82 views
4

我们有一个广泛的代码库,目前使用原始指针,我希望能够迁移到unique_ptr。但是,许多函数都将raw指针作为参数,而unique_ptr不能用于这些情况。我意识到我可以使用get()方法来传递原始指针,但是这增加了我必须接触的代码行数,并且我觉得它有点不雅观。我滚我自己的unique_ptr看起来像这样:在unique_ptr上有一个演员操作符是否危险?

template <class T> 
class my_unique_ptr: public unique_ptr <T> 
{ 
    public: 

    operator T*() { return get(); }; 
}; 

每当我到一个功能PARM一个希望将原始指针提供my_unique_ptr时,它自动地把它变成原始指针。

问题:这样做有什么固有的危险吗?我原以为这是unique_ptr实现的一部分,所以我假设它的省略是故意的 - 有谁知道为什么?

+0

好吧,你可以试试'cout << my_unique_ptr ()<< endl;' –

+1

一般来说,隐式转换是不好的。类型的存在是有原因的,转换应该是明确的。 – GManNickG

+1

@GManNickG:只要他们知道那个时候,里奇定义了内建类型之间的隐含转换。 –

回答

4

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

另外请确保您不要在原始指针上调用delete(即使间接)。

还有另一件事,以确保为您不要创建另一个智能指针,是以指针的所有权(如另一uniqe_ptr<>) - 见删除上面

的原因音符为​​没有做转换为你自动地(并且你明确地呼叫get())是为了确保你能够控制你何时访问原始指针(以避免上述可能以其他方式静默发生的问题)

+3

如果没有别的,缺乏转换可以防止新手的灾难(new int());删除;从编译:-)我不能立即想到任何非新手错误的情况下,有人会错误地删除一个指针,其资源,他们不拥有,以及需要调用'get( )'阻止他们这样做。 –

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

哇,我没想到这是最受欢迎的答案,因为其他人有很好的描述。 –

1

在unique_ptr上有一个演员操作符是危险的吗?

编辑看评论

---不,这当然应该不会有危险---: 事实上的标准需要 explicit转换为“安全布尔'(见Safe Bool Idiom)。

说明用于编辑:

新标准(也引入的unique_ptr)引入explicit operator T()转换。它仍然适用于unique_ptr 好像它是一个隐式转换,因为if,while,for(;x;)确实自动上下文转换为bool。

在我的防守,我的知识主要是基于C++ 03库like Boost which do定义转换unspecified-bool-typeimplicit

我希望这仍然是其他人的信息。


(见其他的答案为更典型的治疗,包括转换到原始指针)上的unique_ptr

+2

OP特意要求一个演员操作符'T *'。 – HighCommander4

+0

事实并非如此,该标准要求对bool进行明确的*转换,而bool则依赖于对bool的上下文转换。 –

+0

@HighCommander:嗯,我可以非常明确地回答我的问题。它是问题的标题。不过,@LucDanton有一个更好的观点。我没有('有意识地')意识到在某些上下文中的使用实际上会触发_explicit_转换为bool。嗯。学会了今天的东西:) – sehe

2

主要“危险”中提供的隐式转换运算符(以原始指针)从茎unique_ptr应该为单一所有权语义建模。这也是为什么它不可能复制unique_ptr,但它可以被移动。

考虑这个“危险”的例子:

class A {}; 

/* ... */ 

unique_ptr<A> a(new A); 

A* a2 = a; 
unique_ptr<A> a3(a2); 

现在 unique_ptr S模式在对象单一所有制的语义指向和自由世界的命运 - 不,在宇宙 - 挂在天平上。

好吧,我有点戏剧性,但这就是主意。

就解决方法而言,我通常只需在指针上调用.get()并完成它,小心地认识到我只是got()上缺少所有权。

鉴于您有一个很大的遗留代码库,您尝试使用unique_ptr进行迁移,我认为您的转换包装很好 - 但只是假设您和您的同事不会在未来维护此代码时。如果这是你可能发现的可能性(我通常会因为我是偏执狂),我会尝试改进所有现有的代码,以显式调用.get(),而不是提供隐式转换。编译器会很高兴地找到你需要做出这个改变的所有实例。