簡體   English   中英

如何通過引用將存儲在列表中的結構成員傳遞給函數?

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

我有一個程序用結構填充 STL 鏈表,我試圖從列表上的節點(我目前通過迭代器使用的節點)傳遞結構成員。 我試圖完成的一件事是一個計算運行平均值的函數。 我不想在結構中存儲計數和總數,然后在輸出時計算平均值,而是將計數和平均值存儲在結構中,從而在重新計算平均值后丟棄我的數量值。 我的結構是這樣的:

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()是指向最后一個元素的指針
  • *it是對指向元素的引用
  • it != container.end()是你如何判斷你是否在最后
  • it->x是指向元素的成員
  • 從容器中移除一個對象可能會使未完成的迭代器失效,這取決於幾個因素。
  • ++it可能比it++更有效率it++

編輯:OP 詢問:

我不是遍歷列表並在每個節點上運行 calc_average,而是遍歷列表以查找特定的項目值。 一旦找到感興趣的節點,我就會在該特定節點上調用 calc_average 函數。 我只是不需要 for 循環。 相反,我會到達我想要的迭代器,並通過 *it 將其傳遞給 void DoSomething ?

我想你現在明白它是如何工作的了。 您將有一些代碼來搜索指定的節點,然后還有一些其他代碼來調用您的函數:

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

將迭代器視為指向列表中元素的指針。 因此, calc_averagecalc_average函數作用於calc_average各個成員, mystruct讓它引用一個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 ) );

是的,在我看來這一切都是正確的。 您可以將迭代器(尤其是標准容器的迭代器)視為指針,但實際上它們實際上是看起來像指針的類。 不過,您可以將它們視為指針。

我目前正在處理動態內容,我發現我有一個 SPRITE 結構 std::list characters_spr; 我通過 SPRITE 字符聲明一個字符然后我使用

characters_spr.push_back(character)

然后我使用 for 循環遍歷列表

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

在 somefunction 我有 somefunction(SPRITE &spr, .....................)

當 somefunction 被調用時,它會更新列表中字符的字符數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM