2016-11-07 93 views
3

我是一名自學成才的C++程序員(仍處於新手級別)。C++ Vectors插入新對象

我想我已經瞭解了C++的工作原理,但是我不能用這種方式來包裝我的頭: 我想創建一個std :: vector並使用定義好的類的不同元素來填充std :: vector:

// other code 

while (getline(cfgDataStream, cfgData)) //parsing cycle of the config file 
{ 

    std::stringstream ss(cfgData); //creating a stream in order to fill fields 
    ss >> string1 >> IP1 >> IP2 >> PORT2 >> INDEX; 
    //they are all strings save the last one, which is a int 
    if (ss.fail()) 
    { 
     //bad things happen 
    } 

//FIRST IDEA: Using insert() 

    CModbusServer MBtemp* = new CModbusServer(this, IP2.c_str(), PORT2, INDEX) 
    std::vector<CModbusServer*>::iterator iterator = this->m_pServerCollection.begin(); //I get the vector initial position 

m_pServerCollection.insert(iterator + (INDEX), MBTemp); // I put the new object in the right index (I don't trust the order in the config file) 


//SECOND IDEA: Using push_back() 

    m_pServerCollection.push_back(new CModbusServer(this, IP2.c_str(), PORT2, INDEX)); //I attach each new object to the end of vector (i trust the order in the config file) 
} 

基本上我想創建CModbusServer的一個對象,並插入其指針在載體中,從而使我在每個矢量位置n不同CModbusServer對象。 這是我迷路的地方,我嘗試了兩種插入方式(如代碼所示),但沒有成功。

CModbusServer除其他外還有一個const char * ipAddress字段。如果我嘗試訪問該字段(即在.Format(_T("%S))函數中使用它),我會得到隨機數據。試圖明白爲什麼我注意到,在向量中,我沒有n個不同的對象,而是使用new CModbusServer(this, IP2.c_str(), PORT2, INDEX)創建的最後一個對象的n個副本。可能發生這種情況是因爲我有一個指針向量,但這些應該是指向不同對象的指針......

我正在使用Visual Studio 2015與MFC爲了實現基於對話框的應用程序。我有一個AppEngine類,它從其他類中調用方法,並具有CModbusServer元素的向量。 CModbusServer.h如下:

class CModbusServer 
{ 
public:  
    CModbusServer(void *parentEngine, const char* , unsigned short , int); 
    ~CModbusServer(); 
    const char* ipAddress; 
    unsigned short port; 
    int indNode; 
    modbus_t *MBserver; 
    bool isConnected; 
} 

所以,我的問題是:

1)爲什麼我不能訪問的ip地址字段(而不是讀「192.0.2.1」我讀隨機字符),而我理論上應該能夠使用theApp.CModbusServerVector[properIndex]->ipAddress來讀取它?

2)我在填充矢量時犯了一個錯誤,但我看不到它在哪裏,最重要的是,它爲什麼錯了。

感謝您的幫助,請原諒我的英文和任何遺漏。

編輯:

CModbusServer的構造函數的代碼是這樣的:

CModbusServer::CModbusServer(void *pE, const char* ip, unsigned short nport, int ind) 
: parentEngine(pE), //used in order to keep track of the parent dialog 
ipAddress(ip), 
port(nport), 
indNode(ind) 
{ 
this->isConnected = false; 
this->m_socket = INVALID_SOCKET; 

memset(&m_socketstructhint, 0, sizeof m_socketstructhint); 
m_socketstructhint.ai_family = AF_UNSPEC; 
m_socketstructhint.ai_socktype = SOCK_STREAM; 
m_socketstructhint.ai_protocol = IPPROTO_TCP; 

MBserver = modbus_new_tcp(ipAddress, (int)nport); 


} 

請告訴我,如果我遺漏任何其他有用的信息。

最初我用CString來管理字符串,但後來我遇到了越來越多的問題,最後得到了一個編譯和const char*工作代碼。我設法建立了一個連接並讀取所需的modbus寄存器,但之後我陷入了isAddress打印問題。

modbus_new_tc(ip,port)是在libmodbus庫中找到的一種方法,libmodbus庫是爲我必須使用的C編寫的免費軟件庫。

編輯2:有關angew答案:

所以,如果我是正確的,發生的事情是,我創建一個臨時組指針,由構造函數中使用的(我現在已經增加了相關碼)。但是,不應該是構建的對象與我通過的參數無關嗎?這些參數不是被複制的嗎?對不起,如果問題很愚蠢,但我還在學習。

索引是連續的,儘管在配置文件中也可能是0-1-2-3(每行1個)或0-3-1-2,這就是我所說的「不信任他們」。

由於push_back方法有相同的問題,可能問題是在構造函數中。令我感到困惑的是,通過逐步執行,我可以看到,while循環的每次迭代都會得到新的正確數據,但是放入第i個位置的時候,會放在第一個位置(即:原始數據:abc,1st run vector = a; 2nd run vector = bb,3rd run vector = ccc)

我不知道std::unique_ptr<>,我會查找它。

我試過使用std:string甚至CString,但問題在於libmodbus庫。

+1

沒有拷貝構造函數/析構函數/賦值/移動操作符的類中的原始指針可能是危險的。 – doctorlove

+1

如果您正在學習C++,您可能會發現我們的[良好C++書籍列表](http://stackoverflow.com/q/388242/1782465)有用。 – Angew

回答

6

std::string上調用c_str會返回一個指向存儲在該std::string實例中的內部數據的「實時」指針。指針返回指向一個緩衝區,只有在調用它的std::string保持活動狀態且未修改時,該緩衝區纔是有效的。

CExtracalModbusServer的構造函數只是存儲傳入的指針。只要IP2在輸入循環的下一次迭代中被重新分配,該指針就變成懸掛的。 (指向的地址仍然相同,但之前位於該地址的緩衝區已被覆蓋或釋放,或者其他地方,換句話說,指針只是懸空)。

至於插入向量:第一種方法(與insert)只能在文件中的索引是順序的並從0開始工作。你需要一個有效的迭代器插入到它的向量中,這裏有效的意思是指向已經在向量中的一個元素,或者指向前一個迭代器(由end()返回的那個)。如果INDEX等於或大於向量的大小,則m_pServerCollection.insert(iterator + (INDEX), MBTemp);將嘗試插入向量之外(實質上是溢出的緩衝區)。無用的行爲隨之而來。

push_back插入數據的方法應該可行,如果你看到它的行爲不當,它可能是早期錯誤(帶有懸掛指針的錯誤)的僞像,或者你沒有顯示的代碼中存在單獨的問題。


與手頭的問題無關,但代碼中包含手動管理的動態內存形式的非常不好的做法。除了在向量中存儲CModbusServer*並在所有正確的位置使用delete手動管理內存,您應該使用std::unique_ptr<CModbusServer>,即使在出現異常情況下,也會爲您處理正確的釋放。

如果CModbusServer在你的控制之下,你應該改變它來存儲std::string而不是const char*。切勿在C++中使用C風格的字符串,除非您必須與C風格的API交互,並且即使在這種情況下,也僅限於交互本身。這又是一個重複的原則:不要手動管理內存。

+0

@MarcomattiaMocellin不要在評論中發表感謝,他們不是那個意思。 SO說「謝謝」的方式是upvote(如果你有足夠的代表)。此外,如果答案解決了您的問題,則應該使用其旁邊的綠色勾號(每個問題最多接受一個接受的答案)考慮[接受](http://stackoverflow.com/help/accepted-answer)。這標誌着問題已經解決,並給你和回答者一些聲譽。 – Angew

+0

謝謝你的回答。 我會再次編輯我的問題,因爲評論會超過限制的570+字符。 –

+0

@MarcomattiaMocellin我已經擴大了答案,我希望它更清晰。複製'const char *'只複製指針,它對它指向的數據不做任何事情。 – Angew