2011-10-28 16 views
0

誰かがなぜこれが起こるか説明していただけますか?初期化が遅れましたか?

1)シングルトンとして実装などのように定義Instance()方法、有しているウィンドウマネージャクラス:

static WindowManager * instance_; 
//... 
WindowManager * WindowManager::instance_ = 0; 
WindowManager & WindowManager::Instance() 
{ 
    if (!instance_) 
     instance_ = new WindowManager(); 
    return *instance_; 
} 

2)新たに参照を返すWindowManager::createWindow方法を私は次のように書かれていますそうのように定義さ作成ウィンドウ:

Window & WindowManager::createWindow() 
{ 
    windows_.push_back(Window()); 
    return windows_.at(windows_.size() - 1); 
} 

3)ウィンドウ内のメッセージを出力しWindow::print方法

私の主なプログラムでは、私は次のように書いています:

ui::Window & win1 = ui::WindowManager::Instance().createWindow(); 
ui::Window & win2 = ui::WindowManager::Instance().createWindow(); 
win1.print("First window"); 
win2.print("Second window"); 

これは動作しません! printへの2回目の呼び出しのみが実行されます(win2)。しかし 、そのように私は、順序を変更した場合:予想通り

ui::Window & win1 = ui::WindowManager::Instance().createWindow(); 
win1.print("First window"); 
ui::Window & win2 = ui::WindowManager::Instance().createWindow(); 
win2.print("Second window"); 

はその後、すべての作品。このような状況で誰かが何らかの光を当てることができれば、どんな助けでも大いに感謝されます。

+0

問題は、 'createWindow'ではスタック上に作成されたオブジェクトへの参照を返しています。このオブジェクトへの参照は、メソッドの終了時に破棄されます。 'windows_'を' std :: vector 'から 'std :: vector 'に変更し、それ以外のものを修正することで私の問題は解決しました。 –

+0

それはあなたの原因ではないが、それは実際の問題を解決するだろう –

+0

これをお読みください:http://stackoverflow.com/questions/1008019/c-singleton-design-pattern/1008289#1008289 –

答えて

2

ここでは、問題を示して簡単な例があります。

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

struct T 
{ 
    int id; 
    T(int id) : id(id) 
     { cout << "created " << id << endl; } 
    T(T const& t) : id(t.id) 
     { cout << "copy: " << t.id << endl; } 
    void print(char const* m) 
     { cout << id << ": " << m << endl; } 
}; 

vector<T> ts; 

T& create(int id) 
{ 
    ts.push_back(T(id)); 
    return ts.at(ts.size() - 1); 
} 

int main() 
{ 
    // Uncomment these lines and compare results 
    //int const max_windows = 10; 
    //ts.reserve(max_windows); 

    T& t1 = create(1); 
    T& t2 = create(2); 
    t1.print("t1"); 
    t2.print("t2"); 
} 

コンパイルをし、それがあるとstdoutに出力されるか見て実行します。 reserve()のコメントを外し、再度コンパイルして実行し、以前の出力と比較します。

問題は、std::vector::push_backがデータの内部的な再割り当てを引き起こすことです。これにより、すべての参照、ポインタ、イテレータが再配置前に取得したベクトル要素に無効になります。

+2

Std :: dequeは苦しんでいませんこの問題は、ほとんどの目的でベクトルとほぼ同じくらい速いです。 –

+0

ありがとう!その間、オブジェクトへのポインタを保持するためにベクトルを変更することで、この問題を回避することができました。マネージャクラス内で一連のオブジェクトを保持するには、C++の推奨方法は何ですか?オブジェクトのコンテナ、またはオブジェクトへのポインタのコンテナ? –

+0

@MooingDuckのコメントを参照してください。また、shared_ptrのハイブリッドコレクションを持つこともできます。 – mloskot

関連する問題