[英]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.