std::vector 覆盖最终值,而不是增长?

发布于 2024-08-20 01:37:02 字数 1455 浏览 13 评论 0原文

我遇到一个问题,使用 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;
}

I'm having an issue where using vector.push_back(value) is overwriting the final value, rather than appending to the end. Why might this happen? I have a sample item in the vector, so it's size never hits zero. Below is the code..

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);
    }
}

This let's my first "sample" value stay in, and will allow for just one more item in the vector. When 2 new entries are added, the second overwrites the first, so the size is never larger than 2.

edit: More code, since this is apparently not the issue?

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

℡寂寞咖啡 2024-08-27 01:37:02

我将冒险猜测:

假设 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 就足以消除这种可能性。

I'm going to hazard a guess:

Suppose MyStruct is declared like

struct MyStruct
{
    const char *sourceAddress;
    // Other Gubbins ...
};

And that ReceivedValue does something like

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;
}

Now, every structure you push into your vector has sourceAddress pointing to the same global buffer, every time you call ReceivedValue it overwrites that buffer with the new string - so every entry in your vector ends up with the same string.

I can't be sure without seeing the rest of your code, but I can be sure that if you follow some of the good C++ style suggestions in the comments to your question this possiblity would go away.

Edit for clarification: there's no need to heap allocate your structures, simply declaring sourceAddress as a std::string would be sufficient to eliminate this possibility.

等风也等你 2024-08-27 01:37:02

您推入数据库的项目的范围即将到期。当您离开创建它们的 {} 时,它们就会被破坏 - 因此对它们的引用不再有效。

您需要将其从 vector 更改为 vector (最好使用 Boost:: 中的安全指针而不是指针,但您明白了) 。

您正在(有限)范围内创建项目并将其推送到向量上(当复制结构时,其中的字符串不是!)然后它会重用相同的内存位置(如果经过适当优化,最有可能)来存储下一个“新”结构以及之后的结构,依此类推。

相反,在有限的范围内创建 MyStruct *myObject = new MyStruct 并分配其值,然后将指针推送到向量。

请记住在清除/销毁它之前删除向量中的所有值!

或者,当然,您可以使用 std::string/CString/whatever 而不是 char数组并通过具有安全复制结构来完全避免该问题。

The scope for the items you are pushing into the database is expiring. They're being destructed when you leave the {} in which they were created - and as such the reference to them is no longer valid.

You need to change it from vector<MyStruct> to vector<MyStruct*> (preferably using safe pointers from Boost:: instead of pointers, but you get the idea).

You are creating the item within the (limited) scope and pushing it onto the vector (while the struct is copied, the strings in it are not!) it then reuses the same memory location (most likely if properly optimized) to store the next "new" struct and the one after that and so on and so forth.

Instead, within the limited scope create MyStruct *myObject = new MyStruct and assign its values, then push the pointer to the vector.

Remember to delete all values from the vector before clearing it/destroying it!!

Or, of course, you could use std::string/CString/whatever instead of a char array and avoid the issue entirely by having a safe-to-copy struct.

把昨日还给我 2024-08-27 01:37:02

ComputerGuru 的答案在另一种选择中有效。您可以为 MyStruct 创建复制构造函数并重载operator=。在这些操作中,您需要将实际字符串复制到新结构中。在 C++ 中,结构只不过是具有默认公共访问而不是默认私有访问的类。另一种替代方法是使用 std::string 而不是 char* 作为字符串值。 C++ 字符串已经具有这种行为。

struct MyStruct {
   std::string sourceAddress;
   int lastSeen;
   int beaconReceived;
};

ComputerGuru's answer works however there in another alternative. You can create a copy constructor and overload operator= for MyStruct. In these operations, you need to copy the actual string into the new struct. In C++, structs are nothing more than classes with default public access instead of default private access. Another alternative is to use std::string instead of char* for the string value. C++ strings already have this behavior.

struct MyStruct {
   std::string sourceAddress;
   int lastSeen;
   int beaconReceived;
};
我家小可爱 2024-08-27 01:37:02

我觉得很奇怪:也许代码的 //snip 部分有问题?

尝试在 push_back 调用之前和之后记录向量的大小(在调试器中或使用 cout),并查看 isNewEntry代码>变量。

Seems odd to me: Maybe there is something wrong with the //snip part of the code?

Try to log the size of the vector before and after the push_back call (either in the debugger or using cout) and also have a look at the isNewEntry variable.

我的黑色迷你裙 2024-08-27 01:37:02

你的代码对我来说看起来没问题。您是否有可能没有传递正确的向量?我的意思是,如果在您尝试添加第三个条目之前您的个人向量以某种方式被重置为其原始的 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.
}

如果这就是您的全部代码,那么问题就很明显了。但它可能隐藏在其他一些代码中。

Your code looks alright to me. Is it possible that you are not passing the right vector in? What I mean is that the behaviour you describe would appear if somehow your Individuals vector is being reset to its orginal 1-entry state before you tried to add the 3rd entry, then it would appear as if your 2nd entry was being overwritten.

Here is what I mean:

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.
}

If this was all your code then the problem would be obvious. But it might be concealed in some other pieces of code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文