繁体   English   中英

std :: unique_ptr的这种行为是预期的吗?

[英]Is this behavior of `std::unique_ptr` expected?

我正在研究一个项目,该项目使用多态性通过重写encode功能来实现对象的encode

现在,该项目一直在使用指针来实现多态行为。 由于我的应用程序是相对较新的应用程序,因此我决定从常规的原始指针切换到智能指针并不难,因为它们将自动管理内存。

在我的函数之一中,我返回了std::unique_ptr 返回智能指针后,我立即想要转换基础原始指针。 因此,对正在发生的事情的过度简化看起来像这样:

std::unique_ptr<something> do_something() {
    return std::unique_ptr<something>(new something());
}

void caller() {
    auto output = static_cast<another*>(do_something().get());
    // Do something with output...
}

我知道std::unique_ptr没有复制构造函数,因为它只能在任何给定瞬间被“拥有”一次。 实现复制构造函数将允许创建重复指针,这违反了该原理。 如果我的理解是正确的,则以下代码使用move构造函数初始化B ,而不复制A

std::unique_ptr<int> get_a() {
    std::unique_ptr<int> A(new int);
    return A;
}

void get_b() {
   auto B = get_a();
}

这正是我想要的行为。 但是,在我的示例中,程序崩溃的时间约为一半。 另一半时间,它似乎可以工作,但是基础指针的内容只是普通的垃圾。 (我怀疑这是未定义的行为,并且get()有时仅返回可读的地址。)

现在,经过一番思考,我得出的结论是,如果B确实正在通过移动构造函数初始化, B本身必须不会是暂时的。 但是,在我的第一个示例中, do_something()的结果是临时的,我将构建它 因此,我决定停止内联对do_something()的调用,然后我立即得到了预期的行为! 每次我在一个临时对象上使用get()时,结果都是不可预测的,根本就是错误的。

我的问题是:

我应该期待unique_ptr这种行为吗? 如果是这样,如何记录这种行为? (更具体地说,我的第一个示例是未定义的行为吗?)还有其他选择( shared_ptr ,也许吗?)可以使我内联函数调用并仍然获得预期的结果?

您在“它们将自动管理内存”语句中总结了此处的关键。

您的unique_ptr (移动后)是一个临时变量,在声明output之后立即超出范围,将它与动态分配的int一起使用,并使output悬空。

临时。 暂时的 如此命名是有充分理由的...

这种行为在许多地方都得到“证明”:存储指向超出范围的对象的指针确实是个坏主意,从此以后使用该指针就被彻底破坏了(是的,它是UB)。

您不能通过切换到其他智能指针来解决这个问题,否:停止“内联”函数调用(并停止使用此术语;这不是“内联”的意思),并确保对象存在的时间可以一直保持通过指针访问它。

auto ptr    = do_something();
auto output = static_cast<another*>(ptr.get());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM