如何将存储在列表中的结构成员通过参考将其传递给函数

How do I pass struct members stored in a list to a function by reference?

本文关键字:参考 函数 结构 存储 列表 成员      更新时间:2023-10-16

我有一个程序,该程序填充了带有structs的stl链接列表,我正在尝试从列表上的节点传递struct成员迭代器)。我要完成的一件事是一个可以计算跑步平均值的函数。我不想将计数和总数存储在结构中,然后在输出时计算平均值,而是想将计数和平均值存储在结构中,从而在平均值被重新计算后丢弃我的数量值。我的结构看起来像这样:

struct mystruct 
{
    string item;
    long avg;
    short count;
} data;

这些结构存储在列表中,并带有迭代器it,该迭代器使我可以在列表中移动。只要我在列表中穿越而it等于我想计算平均值的节点的节点,这将是调用我的平均功能的正确方法?

// prior to running the code below, the `count` and `avg` members for the 
// struct at iterator location `it` are both 1 and 100 respectively
long qty = 50;
calc_average(it->count, it->avg, qty);
cout << "The current count is " << it->count << endl; 
  // Outputs 'The current count is 2'
cout << "The current average is " << it->avg << endl; 
  // Outputs 'The current average is 75'

void calc_average(short &count, long &avg, long quant)
{
    avg = ( (avg * count) + quant ) / (count + 1);
    count++;
}

这看起来正确吗?我正在尝试使用STL列表来实现此功能,但是似乎不仅仅是实现我自己的链接列表类别更令人困惑。我认为我只是对结构以及迭代器的实际工作方式以及实际传递的方式/方式感到困惑。编码对我来说仍然是新的,这是一个学习过程...

谢谢!

假设 X是列表中对象的类型,那么您可以做这样的事情:

void DoSomething(X& object) {
  object.count, object.avg;
}
void DoSomethingElse(int& count, int& average) {
  ...
}
int main() {
   ...
   for(std::list<X>::iterator it=myList.begin(), end=myList.end(); it != end; ++it) {
     DoSomething(*it); // how I'd do it
     DoSomethingElse(it->count, it->avg); // Equally valid way that you did it
   }
   ...
}

只记得:

  • container.begin()是一个指向第一个元素的指针
  • container.end()是一个指向一past的指针
  • *it是对尖头元素的引用
  • it != container.end()是您告诉您是否在结尾
  • 的方式
  • it->x是指向元素的成员
  • 根据几个因素,从容器中删除对象可能使未偿还的迭代器无效。
  • ++it可能比it++
  • 更有效

编辑:OP问:

我不是在列表中迭代并在每个节点上运行calc_average,而是在列表中迭代寻找特定的项目值。一旦找到一个感兴趣的人,我将在该特定节点上调用Calc_average函数。我只是不需要循环。相反,我会到达我想要的迭代器,然后通过 *将其传递给空白?

我认为您了解它现在的工作原理。您将有一些代码来搜索指示的节点,然后再调用您的功能:

   std::list<X>::iterator it, end;
   for(it=myList.begin(), end=myList.end(); it != end; ++it) {
     // Look for the special node:
     if( it->magicValue == 42 ) {
       // We found it!
       break;
     }
   }
    // Either it is equal to end (boo!) or it points to the special node (yay!)
   if( it == end ) {
      std::cerr << "Could not find special node!n";
   }
   if( it != end ) {
      DoSomething(*it);
   }

将迭代器视为指向列表中元素的指针。因此,与其对mystruct的各个成员进行calc_average函数,您可能希望将其引用对mystruct对象并使用该对象进行操作。

例如:

void do_work( mystruct& s )
{
  ++s.count;
}
std::list<mystruct> mylist;
// populate list
std::for_each( mylist.begin(), mylist.end(), do_work );

您也可以通过基于范围的for循环达到相同的效果

for( auto& elem : mylist ) {
  do_work( elem );
}

我将以

的方式重写calc_average功能
void calc_average( mystruct& s, long quant )
{
    s.avg = ( (s.avg * s.count) + quant ) / (s.count + 1);
    s.count++;
}

要与基于范围的for循环一起使用它是微不足道的,但是要与std::for_each一起使用它,您必须使用std::bind绑定quant参数。

std::for_each( mylist.begin(), mylist.end(), 
  std::bind( calc_average, std::placeholders::_1, qty ) );

是的,这对我来说似乎都是正确的。您可以将迭代器(尤其是标准容器的迭代器)视为指针,尽管实际上它们实际上是类似于指针的类。不过,您可以将它们视为指针。

我目前正在使用动态内容,我发现我有一个精灵结构std :: list targe_spr;我用精灵角色声明角色,然后我使用

characters_spr.push_back(character)

然后我使用for循环迭代列表

for(SPRITE &character : characters_spr){
   somefunction(character, ....);
}

在某种功能中某个功能(Sprite&amp; spr,........................................................................................................................................................................................................................................................................................................................................................................................................................

,当称为某些功能时,它会更新列表中字符的字符数据。