5

我们有一个广泛的代码库,目前使用原始指针,我希望迁移到 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

4 回答 4

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.
}
于 2012-06-21T23:09:23.437 回答
5

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

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

还要确保的另一件事是,您不会创建另一个拥有指针所有权的智能指针(例如另一个uniqe_ptr<>)——请参阅上面的删除注释

unique_ptr<>不自动为您进行转换(并且您是否显式调用)的原因get()是为了确保您可以控制何时访问原始指针(以避免上述问题可能会以其他方式静默发生)

于 2012-06-21T20:44:24.990 回答
2

在 a 上提供隐式转换运算符(到原始指针)的主要“危险”unique_ptr源于unique_ptr应该对单一所有权语义建模的事实。这也是为什么不能复制 a unique_ptr,但可以移动它的原因。

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

class A {};

/* ... */

unique_ptr<A> a(new A);

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

现在两个 unique_ptrs 模型对指向的对象的单一所有权语义,自由世界的命运——不,宇宙——悬而未决。

好吧,我有点戏剧化,但这就是想法。

就解决方法而言,我通常只会调用.get()指针并完成它,小心地认识到我只是got().

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

于 2012-06-22T13:06:41.990 回答
1

在 unique_ptr 上使用强制转换运算符是否危险?

编辑看评论

---不,它当然不应该是危险的---:事实上,标准要求隐式 explicit转换为“安全布尔”(参见安全布尔成语)。

编辑说明:

新标准(也引入了 unique_ptr)引入了explicit operator T()演员表。它仍然适用于 unique_ptr ,就好像它是隐式转换一样,因为,if会自动上下文转换为 bool。whilefor(;x;)

在我的辩护中,我的知识主要基于像Boost这样的 C++03 库,它们确实定义了到unspecified-bool-type 隐式的转换。

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


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

于 2012-06-21T23:19:47.557 回答