【问题标题】:Pitfalls of "making" unique_ptr<T> implicitly convertible to T*?“使” unique_ptr<T> 隐式转换为 T* 的陷阱?
【发布时间】:2016-11-07 21:38:29
【问题描述】:

我刚看完

Add implicit conversion from unique_ptr<T> to T*

它侧重于如何做部分,而不是我应该做的部分。我也不是问你是否认为这是一个好主意,但我问的是我可能会遇到的具体陷阱,或者如果我将unique_ptr 子类化以将隐式转换的功能添加到原始指针(所以我可以直接将它传递给带指针的函数,而不使用get())。

【问题讨论】:

  • 与使用get()没有太大区别,适用于后者的所有陷阱也适用于隐式转换。
  • @πάνταῥεῖ:但是另一个方向呢?可能类似于使用 STL 数据结构的意外模板实例化选择?我不知道,恶魔般的东西。

标签: c++ smart-pointers implicit-conversion unique-ptr subclassing


【解决方案1】:

考虑一下这个稍微做作的案例:

X* px;
{
    unique_ptr<X> ux = new X;
    px = ux; // implicit conversion
}
px->method();

当这样呈现时,对 px->method 的调用显然会失败(或者不会,这会更糟),但是如果这段代码更复杂(比如调用以 X* 作为参数的方法, 晦涩的错误可能不会被发现。

例如,将 px = ux 替换为对 functionWithMemory(ux) 的调用;

void functionWithMemory(X * px)
{
   static X* oldX = nullptr;
   if(oldX)
   {
      oldX->goodbye();
   }
   px->hello();
   oldX = px;
}

仍然是人为的,但如果你继续扩展它,它开始变得合理。

【讨论】:

  • 好吧,我不知道...将unique_ptr 分配给其他任何东西本身就是潜在泄漏和分段违规的危险信号。事实上,有人可能会争辩说,这比拥有px = ux.get() 更突出更多
  • @einpoklum:当然可以这样说。这不会让你正确
  • @einpoklum 是的。这就是为什么我说“这很明显”。 (尽管单独考虑声明 px = ux 不会引发标志。在开始担心之前,您必须返回并检查 ux 的类型。)
  • 考虑到您的第二个示例-为什么这样的函数也不会成为普通指针的问题?另外 - 如果我在作业的 RHS 上编写带有 unique_ptr 的代码,我通常会说“嗯……我真的应该这样做吗?”我通常希望通过我的 unique_ptr 的 .get()s 并让它在范围结束时死掉/
【解决方案2】:

隐式转换将允许各种废话:

{
    unique_ptr<int> p(new int);

    p + 10; // OK with implicit conversion
    p[3];   // ditto
    bool x = p; // ditto

    unique_ptr<Derived> d(new Derived);
    unique_ptr<Base> b(d); // OK with implicit conversion...oops
                           // These two unique_ptr's own the same object!

}    // double deletion here

【讨论】:

  • @einpoklum 你认为允许在 unique_ptr 上对单个对象进行指针运算和下标是完全合法的吗?
  • @einpoklum 我也看不出双重删除是“完全合法的”。
  • @einpoklum 您认为它完全合法的事实正是为什么应禁止隐式转换!如果您认为它是合法的,那么您可能会这样编写代码,如果您使用在其自动驾驶仪中运行程序的飞机将从天上掉下来并在堪萨斯州西部形成一个巨大的陨石坑。
  • @ein unique ptr 不是“带有 RAII 的原始指针”。它还在语义上防范常见错误。您仍然可以使用指针算术、双重删除等;但你必须先说.get()。隐式转换为指针是充满的陷阱,并且需要.get() 在它们发生之前修复成堆的错误。当您想转换为指针时,成本是 6 个字符,好处是避免了错误。您错过了 move 并且您的代码被双重删除!独特的 ptr 易于使用,很难搞砸。添加隐式转换,它们变得几乎和原始转换一样糟糕!
  • @Yakk 我认为它们会比原始的更糟糕,因为你会产生安全的错觉:)
猜你喜欢
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-01
  • 2011-08-17
  • 2010-10-06
  • 2019-12-02
  • 1970-01-01
相关资源
最近更新 更多