2016-11-07 67 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