这是`std :: unique_ptr`的行为吗?

时间:2015-07-19 02:07:49

标签: c++ memory-management smart-pointers unique-ptr

我有一个我正在研究的项目,它使用多态来通过覆盖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没有复制构造函数,因为它只能拥有&#34;拥有&#34;曾经在任何一个瞬间。实现复制构造函数将允许创建重复指针,违背此原则。如果我的理解是正确的,则以下代码使用移动构造函数初始化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,也许?)允许我内联函数调用并仍然得到预期的结果?

1 个答案:

答案 0 :(得分:2)

此处的密钥在您的声明“他们会自动管理内存”中进行了总结。

你的unique_ptr(移动后)是一个临时的,在声明output之后立即超出范围,采用动态分配int并离开{{1晃来晃去。

临时。 临时的!这个名字很有道理......

这种行为在许多地方被“记录”:存储指向超出范围的对象的指针是一个非常糟糕的主意,从此使用指针完全被打破(是的,这是UB)。

你不能通过切换到其他智能指针来解决这个问题,不能:停止“内联”函数调用(并停止使用这个术语;这不是“内联”意味着什么)并确保对象存在很长时间因为你想通过指针访问它。

output