[英]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_average
讓calc_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.