2017-04-19 10 views
1

私は奇妙なエラーが発生しています。基本型への一意のポインタを返す関数で派生型への一意のポインタを返そうとすると、戻り値が基底型に降格されるようになります。私はそのメソッドやメンバにアクセスすることができず、私が試してみるとsegfaultsプログラムがあります。C++でunique_ptrを持つ派生型を返すことができません

以下の例では、e1を戻り値の型に再割り当てし、その "評価"メソッドを呼び出すと、segfaultsが発生します。不思議なことに、返される前にevalメソッドを呼び出すと正常に動作します。関数の引数の1つとして割り当てられた変数を使用すると、戻り値の型を格納するための新しいオブジェクトを作成すると動作するように見えます。

残念ながら、私のアルゴリズムがそうのような行が必要です。

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; 
} 

注:私は、この例では、ばかげている知っている、それは単に連結フォームです非常に大きなプログラムのこの行で

+1

あなたは何を期待していますか? 'create'への呼び出しは、あなたがそれを使用する前に削除された値への参照を保存しました。 – paddy

答えて

0

e1 = create(*e1, *e2); 

あなたがe1を再割り当てします。これは、e1が(int_expr)を指し示すために使用されたことが(unique_ptrであるため)削除されることを意味します。

新しいものe1は、今すぐ削除されたint_exprへの参照を保持しています(add_expr)。削除されたオブジェクトへの参照を使用しようとすると、定義されていない動作が発生し、場合によってはsegfaultが発生します。

+0

まだe1を使用できるソリューションはありますか? \t auto temp = create(* e1、* e2); \t e1 = std :: move(temp);例えば、 もsegfaultsです。 – cp420

関連する問題