【问题标题】:Can't Return Derived Type With unique_ptr in C++无法在 C++ 中返回具有 unique_ptr 的派生类型
【发布时间】:2017-09-15 01:20:28
【问题描述】:

我遇到了一个奇怪的错误。当我尝试在返回指向基类型的唯一指针的函数中返回指向派生类型的唯一指针时,就好像返回值被降级为基类型一样。我无法访问它的任何方法或成员,如果我尝试访问,程序会出现段错误。

如果我尝试将 e1 重新分配给返回类型并调用其“eval”方法,则下面的示例会出现段错误。奇怪的是,在返回之前调用 eval 方法可以正常工作。当我使用分配的变量作为函数的参数之一时,似乎会发生这种情况,因为创建一个新对象来存储返回类型确实有效。

不幸的是,我的算法需要这样一行:

e1 = create( *e1, *e2 );

完整代码如下:

#include <memory>
#include <iostream>

class expr
{
public:
    virtual int eval() = 0;
    virtual ~expr() = default;
};

class add_expr : public expr
{
    expr& e1;
    expr& e2;
public:
    add_expr( expr& e1, expr& e2 ): e1(e1), e2(e2) {}
    int eval(){ return e1.eval() + e2.eval(); }
};

class int_expr : public expr
{
    int value;
public:
    int_expr( int value ) : value(value) {}
    int eval(){ return value; }
};

std::unique_ptr<expr> create( expr& ast1, expr& ast2 );

int main()
{
    auto e1 = std::unique_ptr<expr>( new int_expr( 10 ) );
    auto e2 = std::unique_ptr<expr>( new int_expr( 10 ) );
    e1 = create( *e1, *e2 );

    // this seg faults
    std::cout << e1->eval() << '\n';

    // this works properly
    auto e3 = create( *e1, *e2 );
    e3->eval();
    return 0;
}

std::unique_ptr<expr> create( expr& ast1, expr& ast2 )
{
    auto r = std::unique_ptr<expr>( new add_expr( ast1, ast2 ) );

    // this works properly
    std::cout << r->eval() << '\n';
    return r;
}

注意:我知道这个例子很荒谬,它只是一个非常大的程序的合并形式。

【问题讨论】:

  • 你期待什么?您对 create 的调用存储了对在您使用之前已删除的值的引用。

标签: c++ stl segmentation-fault polymorphism unique-ptr


【解决方案1】:

在这一行:

e1 = create( *e1, *e2 );

您重新分配e1。这意味着 e1 过去指向的东西(int_expr)被删除(因为它是 unique_ptr)。

现在e1 指向的新事物(add_expr)仍然包含对刚刚被删除的 int_expr 的引用。当它尝试使用对已删除对象的引用时,会遇到未定义的行为,在您的情况下,会遇到段错误。

【讨论】:

  • 是否有解决方案仍然允许我使用 e1?自动温度 = 创建(*e1,*e2); e1 = std::move( temp );例如,还有段错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-29
  • 2018-10-10
  • 1970-01-01
相关资源
最近更新 更多