2017-02-22 6 views
0

次のコードは、書籍 "Design Patterns Explained Simply"の例です。私は他の質問の提案された方法を使用してみましたが、悪い結果がありました。この問題はどのように把握できますか:警告:一時的なアドレスを取得 - C++

commands[0] = &SimpleCommand(&object, &Number::dubble); 

"警告:一時的にアドレスを取得する"

#include <iostream> 
#include <vector> 
using namespace std; 

class Number 
{ 
    public: 
    void dubble(int &value) 
    { 
     value *= 2; 
    } 
}; 

class Command 
{ 
    public: 
    virtual void execute(int &) = 0; 
}; 

class SimpleCommand: public Command 
{ 
    typedef void(Number:: *Action)(int &); 
    Number *receiver; 
    Action action; 
    public: 
    SimpleCommand(Number *rec, Action act) 
    { 
     receiver = rec; 
     action = act; 
    } 
    /*virtual*/void execute(int &num) 
    { 
     (receiver->*action)(num); 
    } 
}; 

class MacroCommand: public Command 
{ 
    vector < Command * > list; 
    public: 
    void add(Command *cmd) 
    { 
     list.push_back(cmd); 
    } 
    /*virtual*/void execute(int &num) 
    { 
     for (unsigned int i = 0; i < list.size(); i++) 
      list[i]->execute(num); 
    } 
}; 

int main() 
{ 
    Number object; 
    Command *commands[3]; 
    commands[0] = &SimpleCommand(&object, &Number::dubble); // "warning: taking address of temporary" 

    MacroCommand two; 
    two.add(commands[0]); 
    two.add(commands[0]); 
    commands[1] = &two; 

    MacroCommand four; 
    four.add(&two); 
    four.add(&two); 
    commands[2] = &four; 

    int num, index; 
    while (true) 
    { 
    cout << "Enter number selection (0=2x 1=4x 2=16x): "; 
    cin >> num >> index; 
    commands[index]->execute(num); 
    cout << " " << num << '\n'; 
    } 
} 
+0

質問にタグCとして追加しないでくださいC++、C++ 11、C++ 14。 –

+2

私たちは正確なエラーとこのエラーが報告された行を返します – YSC

+0

@JonathanLeffler私はそれがC++ 11またはC++ 14またはvisual-C++にタグ付けされるべきであることさえ確信していません – YSC

答えて

1

違反行は、の3分の1です。この中

Number object; 
Command *commands[3]; 
commands[0] = &SimpleCommand(&object, &Number::dubble); // "warning: taking address of temporary" 

SimpleCommand(&object, &Number::dubble)は、文の終わりに存在しなくなる、一時的に構築し、&は、そのアドレスを取ります。したがって、警告は - ポインタはぶら下がります(存在しなくなったオブジェクトを指す)。そのポインタを参照解除すると、未定義の動作が発生します。コンパイラはこれを診断する必要はありませんが、あなたが好きです。

他のオブジェクトと同じように、オブジェクトを作成してそのアドレスを保存します。 command[0]が存在することがsimpleなくなる後に使用されている場合、これは同じ問題に遭遇すること

SimpleCommand simple(&object, &Number::dubble); 
commands[0] = &simple; 

は注意してください。より現実的なコード(例えば、おもちゃの中のすべてのものではなく、main())は、指摘されたオブジェクトが存在しなくなった後に、容易に存在し続け、使用されているという問題を未解決の問題コンパイラがそれを認識して警告を出す可能性は低いです。

+0

一般的には(つまり、すべてがメインにあるおもちゃの例ではない)、これは 'simple'が範囲外になるときと同じ問題を抱えることに注意してください。 – Useless

+0

@Useless - それは本当です。まもなくそのメモを追加します。 – Peter

+0

さらに、スマートポインタを使用してください。 'std :: vector コマンド。 commands.push_back(std :: make_shared (&object、&Number :: dubble));などです。 –

1
SimpleCommand(&object, &Number::dubble) 

右辺値と呼ばれるものを作成します。これは文の最後に破棄される一時的な値なので、参照を保持しないでください。

関連する問題