I have two std::map<> objects a and b and would like to move (extract + insert) some elements (nodes) from one map to the other based on some predicate p.
for (auto i = a.begin(); i != a.end(); ++i)
if (p(*i))
b.insert(a.extract(i))
Run Code Online (Sandbox Code Playgroud)
This code segfaults in clang. I assume the problem is the increment of i after its node has been extracted from a.
Is the right/only way to fix this by using a post-increment?, E.g.:
for …Run Code Online (Sandbox Code Playgroud) void replace(vector<string> my_vector_2, string old, string replacement){
vector<string>::iterator it;
for (it = my_vector_2.begin(); it != my_vector_2.end(); ++it){
if (*it==old){
my_vector_2.erase(it);
my_vector_2.insert(it,replacement);
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以,我希望这个函数用字符串替换替换向量中所有出现的字符串old.但是在调用此函数时,根本不会更改向量.我不确定我是否正确使用擦除和插入功能.有任何想法吗?
注意:我没有意识到指针被认为是迭代器,因此有人可能会认为我所谓的缺乏内存地址稳定性应该称为迭代器失效.请阅读副本,以获得更抽象和更健全的问题.
我的问题与这个问题有关:当push_back新元素到std :: vector时,C++引用会发生变化.
我想使用一组对象,为简单起见,这些对象在内存中只存在一次.因此,我想使用一个容器,如std :: vector,来存储所有对象一次.然后我将使用指向其他结构中的对象的指针.不幸的是,std :: vector可能会改变它元素的内存地址,因此使用指向这些元素的指针是不明确的.我需要指针,因为我想使用其他结构来引用这些对象,比如std :: priority_queue或其他std数据结构.
在特定情况下,对象是图算法中连接的标签,这意味着它们是在整个算法中创建的,因此不能预先分配.这意味着std :: vector是不够的,因为它可能会重定位其内容,使指向std :: priority_queues或其他数据结构中可能存在的这些标签的指针无效.
但是,我需要标签的唯一时刻是创建它们的时候或者我可以从包含数据结构以外的数据结构访问它们.因此,我永远不需要从容器中获取第n个元素,我只需要能够将对象保留在堆栈或堆上,并在创建它们时获取指针以在其他结构中使用它.最后,当容器从堆栈中弹出时,其中的元素需要很好地清理.我认为std :: list可能是合适的,因为我对抽象链表的知识永远不需要重新分配; 允许稳定的指针.
但是,我无法找到std :: lists的指针稳定性为何.也许有一些优越的东西,一些容器类完全符合我的要求.当然,我总是可以使用new,将所有指针追加到std :: list并迭代在最后执行删除.但这不是我喜欢的方式,因为它需要更多的内存管理,因为我认为应该只需要获得稳定的指针.
问题: std :: list 指针是否稳定?有比std :: list更好的解决方案吗?
为了说明这个问题,我也做了这个例子:http://ideone.com/OZYeuw.用std :: vector替换std :: list,行为变得不确定.
#include <iostream>
#include <list>
#include <queue>
#include <vector>
struct Foo {
Foo(int _a) : a(_a) {}
int a;
};
struct FooComparator …Run Code Online (Sandbox Code Playgroud) 我似乎无法找到关于迭代器是否保持它们迭代的底层对象的大量信息.
如果我创建一个迭代器,那么提供它的对象超出了范围,迭代器的存在是否会阻止它被破坏?
这是一个非常简单的例子,仅用于说明该场景:
// This class takes a copy of iterators to use them later
class Data {
public:
Data(std::vector<int>::iterator start, std::vector<int>::iterator end)
: start(start),
end(end)
{}
void show() {
// Use this->start and this->end for some purpose
}
private:
std::vector<int>::iterator start;
std::vector<int>::iterator end;
};
Data test() {
std::vector<int> v{1, 2, 3};
Data d(v.begin(), v.end());
d.show(); // this would be ok
return d;
}
int main(void) {
Data d = test();
d.show(); // What happens here?
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,Data对象正在存储迭代器的副本,这对第一次 …
使用擦除方法时,地图中的迭代器何时以及如何失效?
例如 :
std :: map < int , int > aMap ;
aMap [ 33 ] = 1 ;
aMap [ 42 ] = 10000 ;
aMap [ 69 ] = 100 ;
aMap [ 666 ] = -1 ;
std :: map < int , int > :: iterator itEnd = aMap.lower_bound ( 50 ) ;
for ( std :: map < int , int > :: iterator it = aMap.begin ( ) ;
it != itEnd ; …Run Code Online (Sandbox Code Playgroud) 问题是std::list用于实现O(1)清除列表项的推荐方法是什么?
通常,当我选择双向链表时,我希望能够在O(1)时间内从列表中删除元素,然后在O(1)时间内将其移动到不同的列表中.如果元素有自己的prev和next指针,那么完成工作就没有真正的诀窍.如果列表是双向链接循环列表,则删除不一定需要知道包含该项目的列表.
根据迭代器失效规则,std::list迭代器非常耐用.因此,std::list在我自己的项目上使用时,我似乎得到了我想要的行为,就是在我的类中隐藏一个迭代器,以及包含列表.
class Item {
typedef std::shared_ptr<Item> Ptr;
struct Ref {
std::list<Ptr>::iterator iter_;
std::list<Ptr> *list_;
};
Ref ref_;
//...
};
Run Code Online (Sandbox Code Playgroud)
这有一个缺点,我需要创建自己的装饰版本std::list,知道ref_每当项目添加到列表时更新.我想不出一种不需要嵌入式迭代器的方法,因为没有一种方法意味着擦除会首先引发O(n)查找操作.
使用O(1)擦除的推荐方法是什么std::list?或者,是否有更好的方法来实现目标?
在过去,我通过实现自己的列表数据结构来实现这一点,其中放置在列表中的项目具有其自己的next和prev指针.管理这些指针很自然,因为它们是列表操作本身固有的(我的列表实现的API调整指针).如果我想使用STL,那么最好的方法是什么?我提出了嵌入迭代器的稻草人提议.有更好的方法吗?
如果需要具体的用例,请考虑使用计时器.创建计时器时,会将其放入适当的列表中.如果取消,则希望有效地将其除去.(此特定示例可以通过标记而不是删除来解决,但它是实现取消的有效方法.)可根据请求提供其他用例.
我探索的另一个选择是将a std::list与a 融合std::unordered_map以创建指针类型的专用列表.这是更重量级的(因为哈希表),但提供了一个非常接近接口级标准容器的容器,并给我O(1)删除列表元素.稻草人提案中缺少的唯一特征是指向当前包含该项目的列表的指针.我已在CodeReview上提出当前的实现以征求意见.
下面的代码按预期工作(测试通过)但我想知道如果以这种方式使用迭代器在c ++中被认为是一种不好的做法,或者它是否正常.
也许这是特定的std::vector,其他集合表现不同,最佳实践在集合(甚至他们的实现)之间有所不同?
在其他语言中肯定不行,并且大多数情况下更改集合将使迭代器无效并抛出异常.
BOOST_AUTO_TEST_CASE (ReverseIteratorExample) {
std::vector<int> myvector;
for(int i = 0; i < 5; i++)
{
myvector.push_back(i);
}
// is this generally a bad idea to change the vector while iterating?
// is it okay in this specific case?
myvector.reserve(myvector.size() + myvector.size() - 2 );
myvector.insert(myvector.end(), myvector.rbegin() + 1, myvector.rend() -1);
int resultset [8] = { 0,1,2,3,4,3,2,1 };
std::vector<int> resultVector( resultset, resultset + sizeof(resultset)/sizeof(resultset[0]) );
BOOST_CHECK_EQUAL_COLLECTIONS(myvector.begin(), myvector.end(), resultVector.begin(), resultVector.end());
}
Run Code Online (Sandbox Code Playgroud)
总结问题:
std::vector和其他集合表现不同? …说我有以下代码:
typedef std::map< int, std::string >::iterator Iterator;
Iterator iter = myMap.begin();
while (iter != myMap.end())
{
Iterator current = iter;
++iter;
maybeDeleteElement( current ) // may call erase.
}
Run Code Online (Sandbox Code Playgroud)
鉴于它std::map是作为红黑树实现的,是否保证地图中的每个元素都只被访问一次?或者修改地图会导致树重新平衡,从而改变迭代序列?
注意:这不是关于任何迭代器是否将被无效的问题.但是迭代器仍然有效并不一定意味着递增它将为您提供与之前相同的下一个元素.
根据stackoverflow和cppreference中描述的迭代器失效规则,我知道除非发生重新哈希,否则迭代器不会对 unordered_map 失效。
如果我使用 std::vector 类比,那么这是否意味着所有插入也发生在迭代器当前指向的位置之前?
我正在修改正在迭代的 unordered_map ,并希望确保不会因迭代器失效而导致任何中断。我至少确保避免使用保留关键字unordered_map Reserve重新哈希
这是我正在编写的示例代码:
// Function to return vector containing the subvector of inputVector with sum desiredSum, this function returns empty vector if sum not found
std::vector<int> sumVectorFunc(const std::vector<int>& inputVector, const int desiredSum){
std::unordered_map< int,std::vector<int> > sumToSubVector{};
sumToSubVector.reserve(desiredSum+1);
// initialization with the zero sum
sumToSubVector[0] = std::vector<int>{};
for(auto itVector : inputVector){ // iterate over the vector of elements
std::unordered_set<int> numbersAddedThisCycle{};
for(auto itSubVectors : sumToSubVector){ // iterate …Run Code Online (Sandbox Code Playgroud) 我编写这个小代码只是为了看看迭代器是如何实际失效的,并且在达到容量之后没有指向向量的更改位置.
这里矢量和容量的大小最初都是5.之后我在向量中插入了一些其他元素,并没有重新初始化我的迭代器指向myvector.begin().49在maximum size of vector is : 1073741823再次打印向量元素之后,这会导致输出中的垃圾值.
我的问题是为什么myvector.begin()在将所有元素复制到新位置后,C++不再使点迭代器成为有效的?
这也可能导致一些难以调试的行为.我知道一种安全的工作方式是在使用之前始终重新初始化迭代器.
#include<iostream>
#include<vector>
#include<stdio.h>
using namespace std;
int main()
{
vector<int> myvector;
vector<int>::iterator it;
int myarray[]= {100,200,300,400};
myvector.insert(it,500);
it=myvector.begin();
myvector.insert(it,myarray,myarray+4);
it=myvector.begin();
for(;it!=myvector.end();++it)
cout <<*it<<endl;
cout <<"size of vector is :" << myvector.size() <<"\n";
cout <<"capacity of vector is : " << myvector.capacity()<<"\n";
cout <<"maximum size of vector is : " << myvector.max_size()<<"\n";
myvector.push_back(600);
for(;it!=myvector.end();++it)
cout <<*it<<endl;
}
Output of program :-
100
200 …Run Code Online (Sandbox Code Playgroud)