我遇到的问题是使用vector.push_back(value)
覆盖最终值,而不是追加到最后。为什么会这样?我在矢量中有一个样本项,所以它的大小永远不会达到零。以下是代码..
void UpdateTable(vector<MyStruct> *Individuals, MyStruct entry)
{
MyStruct someEntry;
bool isNewEntry = true;
for (int i = 0; i < Individuals->size(); i++)
{
if (!(strcmp(Individuals->at(i).sourceAddress, entry.sourceAddress)))
{
isNewEntry = false;
//snip. some work done here.
}
}
if(isNewEntry)
{
Individuals->push_back(entry);
}
}
这是我的第一个“样本”值,并且将允许向量中的另外一个项目。当添加2个新条目时,第二个将覆盖第一个条目,因此大小永远不会大于2.
编辑:更多代码,因为这显然不是问题?
void *TableManagement(void *arg)
{
//NDP table to store discovered devices.
//Filled with a row of sample data.
vector<MyStruct> discoveryTable;
MyStruct sample;
sample.sourceAddress = "Sample";
sample.lastSeen = -1;
sample.beaconReceived = 1;
discoveryTable.push_back(sample);
srand(time(NULL));
while(1)
{
int sleepTime = rand() % 3;
sleep(sleepTime);
MyStruct newDiscovery = ReceivedValue();
if (newDiscovery.lastSeen != -1000) //no new value from receivedValue()
{
UpdateTable(&discoveryTable, newDiscovery);
}
printTable(&discoveryTable);
}
return NULL;
}
答案 0 :(得分:3)
我会冒险猜测:
假设MyStruct
被声明为
struct MyStruct
{
const char *sourceAddress;
// Other Gubbins ...
};
那ReceivedValue
就像
MyStruct ReceivedValue()
{
static char nameBuffer[MAX_NAME_LEN];
// Do some work to get the value, put the name in the buffer
MyStruct s;
s.sourceAddress = nameBuffer;
// Fill out the rest of MyStruct
return s;
}
现在,你推入向量的每个结构都有sourceAddress
指向同一个全局缓冲区,每次调用ReceivedValue
它都会用新字符串覆盖该缓冲区 - 所以向量中的每个条目都结束用相同的字符串。
我不能确定没有看到你的其余代码,但我可以肯定,如果你在评论的评论中遵循一些好的C ++风格的建议,这种可能性就会消失。
编辑以澄清:没有必要堆分配你的结构,简单地将sourceAddress声明为std :: string就足以消除这种可能性。
答案 1 :(得分:2)
您要推送到数据库的项目的范围即将到期。当你离开创建它们的{}
时,它们就会被破坏 - 因此对它们的引用不再有效。
您需要将其从vector<MyStruct>
更改为vector<MyStruct*>
(最好使用Boost ::而不是指针的安全指针,但您明白了。)
您正在(有限的)范围内创建项目并将其推送到向量上(当复制 struct 时,其中的字符串不是!)它然后重新使用相同的内存位置(最有可能是经过适当优化)来存储下一个“新”结构和之后的结构,依此类推等等。
相反,在有限范围内创建MyStruct *myObject = new MyStruct
并分配其值,然后将指针推送到向量。
在清除/销毁之前,请记住delete
矢量中的所有值!!
或者,当然,你可以使用std :: string / CString / whatever而不是char数组,并通过安全复制结构来完全避免这个问题。
答案 2 :(得分:1)
然而,ComputerGuru的答案在另一种选择中有效。您可以为MyStruct创建复制构造函数和重载operator =。在这些操作中,您需要将实际字符串复制到新结构中。在C ++中,结构只不过是具有默认公共访问而不是默认私有访问的类。另一种方法是使用std :: string而不是char *作为字符串值。 C ++字符串已经有这种行为。
struct MyStruct {
std::string sourceAddress;
int lastSeen;
int beaconReceived;
};
答案 3 :(得分:0)
你的代码看起来不错。您是否可能没有传递正确的向量?我的意思是,在您尝试添加第三个条目之前,如果您的Individuals向量被重置为其原始的1条目状态,那么您描述的行为将会出现,然后看起来好像您的第二个条目被覆盖了。
这就是我的意思:
int test_table()
{
string SampleAddresses[] = {"Sample Address 1", "Sample Address 2"};
for (int i = 0; i < 2; i++)
{
// All this work to build the table *should* be done outside the loop; but we've accidentally put it inside
// So the 2nd time around we will destroy all the work we did the 1st time
vector<MyStruct> Individuals;
MyStruct Sample;
Sample.sourceAddress = "Sample Address 0";
Test.push_back(Sample);
// this is all we meant to have in the loop
MyStruct NewEntry;
NewEntry.sourceAddress = SampleAddresses[i];
UpdateTable(Individuals, NewEntry);
}
//Now the table has 2 entries - Sample Address 0 and Sample Address 2.
}
如果这是您的所有代码,那么问题就很明显了。但它可能隐藏在其他一些代码中。
答案 4 :(得分:0)
对我来说似乎很奇怪:可能代码的//snip
部分有问题吗?
尝试在push_back
调用之前和之后(在调试器中或使用cout
)记录向量的大小,并查看isNewEntry
变量。