2017-02-22 73 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

违规行是第三行。

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

在此,SimpleCommand(&object, &Number::dubble)构建了一个临时的,将停止在声明的末尾存在,以及&需要它的地址。因此警告 - 指针将悬空(指向不再存在的对象)。任何解除引用该指针都会导致未定义的行为。编译器不需要诊断,但你的帮忙。

只需按照其他对象一样进行操作:构造对象并存储其地址。

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

注意,这也会遇到同样的问题,如果command[0]之后simple停止使用存在。更实际的代码(例如,不是玩具main()中的所有内容,正如“注释中没有用处”所指出的)很容易就会使commands[0]问题继续存在 - 并被使用 - 在它指向的对象停止存在之后,这也会导致未定义的行为 - 但编译器不太可能识别并发出警告。

+0

请注意,一般情况下(即不是在所有东西都是主要的玩具示例中),当“简单”超出范围时,这可能会遇到同样的问题。 – Useless

+0

@无用 - 的确如此。我会尽快为此添加一条便条。 – Peter

+0

更好的是,使用一个智能指针:'std :: vector 命令; commands.push_back(std :: make_shared (&object,&Number :: dubble));'等等。 –

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

创建一种叫右值。这是临时值,将在声明结束时销毁,因此您不应该继续参考它。