如何将现有对象的地址分配给智能指针?

Tom*_*zyk 20 c++ smart-pointers unique-ptr c++14

#include <memory>

class bar{};

void foo(bar &object){
    std::unique_ptr<bar> pointer = &object;
}
Run Code Online (Sandbox Code Playgroud)

我想将对象的地址分配给指针.上面的代码显然不会编译,因为赋值运算符的右侧需要是std :: unique_ptr.我已经尝试过了:

pointer = std::make_unique<bar>(object)
Run Code Online (Sandbox Code Playgroud)

但它在编译过程中会抛出许多错误.我怎样才能做到这一点?

更新
如答案中所述 - 使用该std::unique_ptr::reset方法导致未定义的行为.现在我知道,在这种情况下我应该使用标准指针.

Ray*_*nda 15

尝试std :: unique_ptr :: reset

void foo(bar &object){
    std::unique_ptr<bar> pointer;
    pointer.reset(&object);
}
Run Code Online (Sandbox Code Playgroud)

但请注意,不建议这样做,不应创建unique_ptr传递给函数的引用.在函数结束时,当pointer它被销毁时,它也会尝试销毁object,并且它不会在函数调用之外可用,从而导致访问内存错误.

示例:这将编译,但会给出运行时错误.

struct bar{ int num;};

void foo(bar &object){
    std::unique_ptr<bar> pointer;
    pointer.reset(&object);
}

int main()
{
    bar obj;
    foo(obj);
    obj.num; // obj is not a valid reference any more.
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

另一方面,您可能需要考虑使用shared_ptr这可以帮助您决定:unique_ptr还是shared_ptr?.

  • 如果有人向我解释为什么投反对票,我会很高兴。 (3认同)
  • @RaydelMiranda 你的例子不好。`bar obj` 对象未分配,因此它并不是您想要讨论的示例。“std::unique_ptr”析构函数中发生的“free()”将针对堆栈内存,您无法释放堆栈内存。展示糟糕的代码是可以的,但从上下文来看,这是不正确的。你应该分配吧。`bar * obj = new bar();`,然后传递引用 `foo(*obj);`。返回时被释放,因此 `obj-&gt;num;` 是未定义的行为。另外你可能想写`std::cout &lt;&lt; obj-&gt;num &lt;&lt; "\n";`。 (2认同)

小智 7

请允许我让你失望,但你不会。您有一个引用,它可以指向动态分配的对象或堆栈分配的对象,或者可能指向动态分配的数组中的对象,该对象不是单独分配的。

\n\n

您希望将其地址放入一个类中,该类将自动对该地址调用删除。这对于上述大多数情况都是无效的。那是错的。因此,永远不应该传递引用并将引用的地址放入智能指针中。尤其是使用reset() 时更是如此。

\n\n

最多,您可能想做的是用新分配的对象初始化智能指针,例如:

\n\n
auto ptr = std::unique_ptr<X>(new X(p1, p2));\n
Run Code Online (Sandbox Code Playgroud)\n\n

切勿获取参考地址。曾经。没原因。这在道德上是错误的。并不是因为引用地址的使用无效,而是因为它可以有效使用;这是因为两个月后,新同事会想要通过智能指针使用该地址,因为他听说现在就是这样做的,然后来到 Stack Overflow 并了解到他们应该使用 \xe2\x80\x9ereset\xe2 \x80\x9d 为该指针。这是错误的,错误得令人痛苦。

\n


Dam*_*mon 5

您只能分配另一个unique_ptrnullptr. 如果你仔细想想,这也是有道理的(虽然reset会让你做你想做的事,但我认为这实际上是 中的一个错误或缺陷unique_ptr)。

Aunique_ptr是指向对象的唯一所有者。当它超出范围时,它将删除该对象。
这意味着您的函数具有接收语义。您传入的指针(或者更确切地说是指向的对象)被消耗,也就是说,它在函数内部“消失”(下沉)。您通过引用传入一个对象(一个甚至不一定是堆分配的对象) ,如果您传入具有自动存储功能的对象,请准备好惊喜!)然后它突然消失了。砰。

应该正确传达接收器语义。您应该传递一个unique_ptras 函数参数。唯一指针无法复制,因此这将迫使该函数的用户使用std::move,从而意识到正在发生的事情。

一个对象“消失”是一个令人讨厌的惊喜,这不应该只是无意中发生的。