![](/img/trans.png)
[英]How to convert a C++ STL vector iterator to a vector reverse iterator?
[英]how to convert iterator of list STL to instance (C++)
這是我第一次使用STL列表,我不確定我是否有可能做到這一點。 我有class_B,它包含class_A的列表,我需要一個帶有ID的class_B中的函數,在列表中搜索具有相同ID的實例,並從列表中獲取指向該列表中實例的指針:
bool class_B::get_pointer(int ID,class_A* pointer2A){
list<class_A>::iterator i;
for(i=class_A.begin();i!=class_A.end();i++){
if((*i).get_id()==ID) {
\\pointer2A=(i);<---------------this is what I'm trying to do
return true;
}
}
pointer2A=NULL;
return false;
}
我該如何執行此操作,是否可以從迭代器轉換為實例?
編輯:
我在多線程程序中使用此函數,我無法將迭代器返回到調用函數,因為另一個線程可能會刪除列表中的元素。
現在我有一個指向我的元素的指針(並且假設它被鎖定以便它不能被刪除),並且另一個線程移除了另一個元素並在列表上執行排序,我將持有的指針會發生什么? (我不知道列表如何重新排列元素,是通過使用復制c'tor復制元素還是通過其他方法來完成?)。
在我的情況下, 無用的答案是最有幫助的(非常感謝),是的,我應該使用對指針的引用,因為我正計划改變它。
你應該這樣寫:
pointer2A= &*i;
這里*i
返回的對象,你可以通過前綴&
作為地址獲得: &*i
。
請注意, i
與&*i
。 有關更一般的討論,請參閱此主題:
無論如何,我建議你把指針本身讀作:
class_A* class_B::get_pointer(int ID)
{
//I assume the name of the list is objA, not class_A
for(list<class_A>::iterator i=objA.begin();i!=objA.end();i++)
{
if( i->get_id()==ID)
{
return &*i;
}
}
return NULL; //or nullptr in C++11
}
或者,在C ++ 11中,您可以使用std::find_if
作為:
auto it = std::find_if(objA.begin(),
objA.end(),
[&](class_A const &a){ return a->get_id() == ID;});
classA *ptr = NULL;
if ( it != objA.end())
ptr = &*it; //get the pointer from iterator
確保get_id
是const
成員函數。
if(i->get_id()==ID) {
pointer2A=&*i;
return true;
}
迭代器被設計為具有與指針類似的語義,因此例如,您可以編寫i->get_id()
就像您有一個指向A的指針一樣。
類似地, *i
產生一個引用A&
,並且&*i
將其轉換回指針 - 它看起來有點笨重(如果i
真的是一個指針,它將是一個身份操作),但它是慣用的。
請注意,這不會做你想要的任何事情 - 調用者的class_A* pointer2A
是按值傳遞的 ,所以只有get_pointer
的指針副本被修改,調用者才會看到該值。 嘗試這個:
bool class_B::get_pointer(int ID, class_A *& pointer2A)
{
list<class_A>::iterator i;
for(i=class_A.begin();i!=class_A.end();i++) {
if(i->get_id()==ID) {
pointer2A=&*i;
return true;
}
}
pointer2A=NULL;
return false;
}
現在, pointer2A
通過引用傳遞,因此調用者的副本會在函數內被修改。
順便說一下,你可以從右到左讀取參數聲明class_A * & pointer2A
,因為“pointer2A是對class_A指針的引用”。
如果你有一個iterator
,你可以通過簡單地解除引用迭代器(它給你一個引用),然后獲取它的地址(它給你一個指針)來獲得一個原始指針。 所以,在你的情況下:
pointer2A = &*i;
這可能看起來像一個奇怪的,笨拙的方式獲得一個指針,它是。 但是當您使用Std Lib中的集合和迭代器時,通常不關心指針。 迭代器是將“STL”組合在一起的粘合劑。 這就是你應該處理的問題,而不是原始指針。
你上面寫的循環肯定會完成你想要完成的工作,但是有更好的方法來實現相同的目標。 (更好是一個主觀術語。)特別是, <algorithm>
庫提供std::find
和std::find_if
,它們就像他們所說的一樣。 他們在集合中找到了一些東西。 find
會找到與你正在尋找的東西相等的東西。 find_if
將找到與您指定的某些條件匹配的內容。 后者是這里使用的合適算法,有兩種主要方法可以使用它。
第一種更“傳統”的方法是使用仿函數:
struct match_id : public std::unary_function<bool, class_A>
{
match_id(int ID) : id_(id) {};
bool operator()(const class_A* rhs) const
{
if( id_ == rhs->get_id() )
return true;
else
return true;
};
/* ... */
list<class_A>::iterator it = std::find_if(objA.begin(), objA.end(), match_id(ID));
此方法適用於C ++ 03或C ++ 11。 有些人不喜歡它,因為它相當冗長。 另一方面,我喜歡它,因為實際的商務邏輯( find_if
調用)比顯式循環更簡潔,更具表現力。
在C ++ 11中,您可以使用lambda代替仿函數:
unsigned ID = 42;
std::find_if( objA.begin(), objB.end(), [&ID](const class_A& rhs) -> bool { return rhs.get_id() == ID; } };
這里有一個權衡。 在專業方面,您不必為仿函數編寫10行左右的代碼,但在con方面,lambda語法很時髦,需要一些時間來習慣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.