2016-06-28 8 views
0

私はC++には新しくプログラミングには向いていませんが、私は非常に困惑しています。私はそのコンストラクタでリストを作成するクラスを持っています。コンストラクタ内のリストのiteratorを呼び出すと、最終値が変更されますか?

私はリストの最終的な価値をプリントアウトしています。これは、一般的にお互いに合っています.1つはlist::end、もう1つはlist::backです。次に、私は主な関数でこのクラスのコンストラクタを呼び出し、作成されたリストにアクセスして、最終的な値を出力しようとします。サンプルコードを以下に示します。

#include <iostream> 
#include <fstream> 
#include <sstream> 
#include <string> 
#include <typeinfo> 
#include <list> 
#include <algorithm> 
#include <queue> 
using namespace std; 
class Process{ 
public: 
    Process(int CB); 
    int CB; 
}; 

Process::Process(int c){ 
    CB = c; 
} 

class Event{ 
public: 
    Event(Process *process); 
    Process *process; 
}; 

Event::Event(Process *ps){ 
    process = ps; 
} 

typedef list<Event> EventList; 

class DES{ 
public: 
    DES(string originFile); 
    EventList events; 
}; 



DES::DES(string originFile){ 
    ifstream infile (originFile.c_str()); 
    string str; 
    while (getline(infile, str)) { 
     // output the line 
     //cout << str << endl; 
     istringstream iss(str); 

     int AT,TC,CB,IO; 
     if (!(iss >> AT >> TC>>CB>>IO)) { 
      cout<<"breaking out of while loop \n"; 
      break; 
     } 
      Process p(CB); 
      Event evt(&p); 
     this->events.push_back(evt); 

    } 

    int cb = this->events.back().process->CB; 
EventList::iterator inserter2 = this->events.begin(); 
EventList::iterator inserter3 = this->events.end(); 

//inserter3--; 

//cout<<"CB after while loop using List<>::end(): " <<inserter3->process->CB<<endl; 
//cout<<"CB after while loop using LIST<>::back "<<cb<<endl; 

    infile.close(); 

} 


int main (int argc, char* argv[]) { 
string inputFileName = argv[1]; 


DES des(argv[1]); 
EventList::iterator b = des.events.end(); 
b--; 
cout<<"CB at back of list in main: "<<b->process->CB<<endl; 

return 0; 
} 

ここで私は混乱するところです。 mainのprintステートメントは、リストの最後の要素のフィールド->process->CBを単に出力するだけなので、コンストラクタのprintステートメントの出力と一致する必要があります。しかし、何らかの理由でこれは私のコンストラクタで//EventList::iterator inserter2 = this->events.begin();という行のコメントを外すときにのみ機能します。同様に、私はその行を保持し、代わりに行EventList::iterator inserter3 = this->events.end();をコメントアウトする場合、それは動作しません。私は両方のイテレータを構築するときだけリストの終わりと始めに、正しい値がmainに出力されます。

誰でもこの奇妙な行動を見せてくれますか?私はC++に精通していないために何か簡単な誤解でなければならないことを知っていますが、この動作は私にとって不自然なようです。

編集:ここではコメントアウトコンストラクタでイテレータの一つと出力されます。

CB after while loop using List<>::end(): 10 
CB after while loop using LIST<>::back 10 
CB at back of list in main: 306496 

そして、ここでコンストラクタでのイテレータの両方で出力されます:

CB after while loop using List<>::end(): 10 
CB after while loop using LIST<>::back 10 
CB at back of list in main: 10 

- Paul

+0

質問を編集し、分離された個々のコードフラグメントを削除し、[mcve]に置き換えてください。 –

+0

また、コメントを削除してください。コードの行はどのようなものか知っています。 – PaulMcKenzie

+0

コメントを削除するコードを編集しました。コードが異なるファイルに存在する場合、どのように組み合わせるべきですか? – Paul

答えて

1

あなたの地域の住所を使用していますか/ここに保存しています:

 Process p(AT,TC,CB,IO); 
     Event evt(AT,&p,CREATED,READY); 

pを宣言するコードブロックが終了すると、そのポインタへの参照は結果として未定義となります。


Processはシンプルintが含まれているので、あなただけの代わりにポインタを使用してのProcessのコピーを格納することができます。これは、少なくとも一貫性のない結果をユーザーに取り除く必要があります

 Event evt(Process(CB)); 

 Process p(CB); 
     Event evt(p); 

または単に:

class Process{ 
public: 
    Process(int CB); 
    int CB; 
}; 

class Event{ 
public: 
    Event(const Process& process); 
    Process process; 
}; 

Event::Event(const Process& ps) : process(ps) {} 

次に、コードの最初のブロックは次のようになります。


あなたが本当にポインタを必要とした場合は、代わりに生のポインタを使用しての必要と認められるなどstd::unique_ptrやifスマートポインタ、std::shared_ptrを考えます。

+0

私はオブジェクト自体ではなくポインターとしてプロセスを保存する必要があると仮定します(実際のクラスははるかに複雑なので、私はこの記事のために単純化しました)。 @Ken Y-Nは、ヒープ上にポインタを格納するために 'Process p = new Process(AT、TC、CB、IO)'を使うことができたと考えました。参照ではなく値でポインタを渡す方法はありますか? – Paul

+0

私は私の答えでそれを言及しました - あなたは 'std :: shared_ptr'を使うことができます - ' typedef std :: shared_ptr ProcessPtr; ProcessPtr p = std :: make_shared (AT、TC、CB、IO) ' - ' p 'のすべての対象が破壊されると、 'delete'が自動的に呼び出されます。 – PaulMcKenzie

+0

素晴らしい、それはまさに私が必要としていたものです。そして、私が思っていたことが不可能ではないことを知っていることは、安心です。 – Paul

関連する問題