在STL容器类(Vector,Dequeue,list,map,multimap,set,multiset)上操作时,Iterator失效的常用规则是什么?是否有可能对C++ STL程序员在处理容器及其迭代器时必须注意的一些一般规则/指南进行分类和总结?
我正在使用C++ std::multimap,我必须循环两个不同的键.有没有一种有效的方法来做到这一点,除了创建两个范围并单独循环这些范围?
这就是我现在这样做的方式:
std::pair<std::multimap<String, Object*>::iterator,std::multimap<String, Object*>::iterator> range;
std::pair<std::multimap<String, Object*>::iterator,std::multimap<String, Object*>::iterator> range2;
// get the range of String key
range = multimap.equal_range(key1);
range2 = multimap.equal_range(key2);
for (std::multimap<String, Object*>::iterator it = range.first; it != range.second; ++it)
{
...
}
for (std::multimap<String, Object*>::iterator it2 = range2.first; it2 != range2.second; ++it2)
{
...
}
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) 两次做某事有一个共同的习惯用法,如下列情况?
for ( int i = 0; i < num_pairs; i++ ) {
cards.push_back( Card(i) );
cards.push_back( Card(i) );
}
Run Code Online (Sandbox Code Playgroud)
我有一种感觉,比引入一个从0到1计数的新循环变量有一个更清晰的方法,特别是因为除了计数之外它没有被使用.
for ( int i = 0; i < num_pairs; i++ )
for ( int j = 0; j < 2; j++ )
cards.push_back( Card(i) );
Run Code Online (Sandbox Code Playgroud)
(Card只是我编写的一些课程,与问题无关.)
struct Struct_t {
int Value1;
int Value2;
};
vector<Struct_t> Struct;
Struct.resize(10, Struct_t());
for (int i = 0; i < 10; ++i)
{
Struct[i].Value1 = (i + 10) * 3;
Struct[i].Value2 = (i + 5) * 2;
}
Run Code Online (Sandbox Code Playgroud)
如何创建指向 Struct[i] 的指针?
我想要做的基本上是这样的,但我相信这可以做得更好:
int value = 6;
Struct_t temp = Struct[value], *s;
s = &temp;
s->Value1 = 42;
s->Value2 = 6;
Run Code Online (Sandbox Code Playgroud)
主要目标是,我可以使用 1 行/函数轻松创建指向 Struct[n] 的指针。
我有一个具有这三个功能的 Holder 对象
unique_ptr<Object> Holder::remove(string objName){
std::vector<unique_ptr<Object>>::iterator object =
find_if(objects.begin(), objects.end(),
[&](unique_ptr<Object> & obj){ return obj->name() == objName;}
);
objects.erase(std::remove(objects.begin(), objects.end(), *object));
return std::move(*object);
}
vector<unique_ptr<Object>> const& Holder::getContent() const {
return this->objects;
}
void Holder::add(unique_ptr<Object> objPtr) {
this->objects.push_back(move(objPtr));
}
Run Code Online (Sandbox Code Playgroud)
我写了一个 CPPunit 测试如下:
void HolderTest::removeObject() {
Holder holder("bag");
unique_ptr<Object> ringPtr(new Object("a"));
holder.add(move(ringPtr));
unique_ptr<Object> swordPtr(new Object("b"));
holder.add(move(swordPtr));
holder.remove("a");
vector<unique_ptr<Object>> const& objects = holder.getContent();
CPPUNIT_ASSERT(objects.size() == 1);
}
Run Code Online (Sandbox Code Playgroud)
这个测试毫无问题地通过,但对我来说很奇怪的是,如果我添加以下行:
const std::string name = objects[0].get()->name();
CPPUNIT_ASSERT_EQUALS("b", name);
Run Code Online (Sandbox Code Playgroud)
然后测试在没有任何消息的情况下崩溃。我在另一个测试中编写了这一行而没有调用 remove 并且它没有任何问题。如果我将向量大小的值更改为 2 或 0 CPPUNIT_ASSERT(objects.size() …
我有一个情况.我已经使用模板化函数完成了我的任务之一.对于这个函数,我通过引用传递迭代器.现在,我必须从向量中删除一些元素.如何仅使用迭代器来完成此操作?Pl找到相应的代码:
template <class BidirectionalIterator, class Iterator> bool
SomeFunc( BidirectionalIterator& first, BidirectionalIterator& last, Iterator anotherVecBegin )
{
while((first+1) != last)
{
if(some_condition)
// delete (first); HOW?
else if(some_other_condition)
// delete (first + 1); HOW?
}
// add something to another vector using anotherVecBegin
return true;
}
Run Code Online (Sandbox Code Playgroud)
有许多已经问过的问题,但它们都有一个上下文的向量.所以myVec.erase(*first)很容易..
我也知道它不是一个非常好的方式,我通过引用传递迭代器.但我遵循简单的规则:在预期某些事情发生变化时使用引用或避免重复复制.我的方案符合第一个条件.
那么如何删除?
这是我正在查看的代码片段:
vector<int> iv = {1,2,3,4,5,6,7,8,9,10};
auto iter = iv.begin(), mid = iv.begin() + iv.size()/2;
for(int count = 100; count; --count ) {
iter = iv.insert(iter, - 1);
cout << "capacity = " << iv.capacity() << "*mid = " << *mid << endl;
}
Run Code Online (Sandbox Code Playgroud)
根据迭代器失效规则:
vector:插入点之前的所有迭代器和引用都不受影响,除非新容器大小大于先前容量(在这种情况下所有迭代器和引用都无效)[23.2.4.3/1] 迭代器失效规则
我明白,因为我在每次插入操作中重新分配"iter"的值,或许我能够保持它的有效性(如果我错了,请纠正我).但是,迭代器"mid"在这种情况下仍然有效,即使我没有在循环中篡改它,也当向量的容量发生变化时.
那么,"mid"在重新分配后如何能够自我更新?
要知道mid是否完全改变,我将代码中的第4行更改为:
iv.insert(iter, -1); // Did not assign it back to iter.
Run Code Online (Sandbox Code Playgroud)
打印在中间取消引用该值的结果表明该更改,并且可能也表明它已失效.(如果我错了,请再次纠正我).
我有一个矢量std :: vector.我想迭代向量找到匹配,如果找到想要返回指向元素的指针,如下所示:
const int * findint(std::vector <int> &v, int a)
{
std::vector<int>::const_iterator i1,i2;
i1 = v.begin();
i2 = v.end();
for(;i1 != i2;++i1) {
if(a== *i1) {
return(i1);
}
}
return(0);
}
Run Code Online (Sandbox Code Playgroud)
这是使用GNU g ++ 2.95.3编译器进行编译和工作正常但不能使用GNU g ++ 4.9.2进行编译并给出以下错误:
error: cannot convert 'std::vector<GenFld>::const_iterator {aka __gnu_cxx::__normal_iterator<const int*, std::vector<int> >}' to 'const int*' in return
[exec] return(i1);
Run Code Online (Sandbox Code Playgroud)
需要帮忙.
我一直在练习我的 C++ 算法知识,并陷入了标准 BK 实现。该算法输出了太多的派系,我似乎不明白为什么。我将图表示为邻接列表:
vector< list<int> > adjacency_list;
Run Code Online (Sandbox Code Playgroud)
我的 BK 函数如下所示:
void graph::BronKerbosch(vector<int> R, vector<int> P, vector<int> X){
if (P.empty() && X.empty()){
result_cliques.insert(R);
}
for (int node : P){
vector<int> intersection = {}, intersectionX = {};
//N(P)
for (int nodeP : adjacency_list[node]){
for (int node2 : P){
if (nodeP == node2){
intersection.push_back(nodeP);
}
}
//N(X)
for (int node3 : X){
if (nodeP == node3){
intersectionX.push_back(nodeP);
}
}
}
R.push_back(node);
BronKerbosch(R,intersection,intersectionX);
P.erase(remove(P.begin(),P.end(),node),P.end());
X.push_back(node);
}
}
Run Code Online (Sandbox Code Playgroud)
我用以下方式称呼它:
void graph::run_BronKerbosch(){
vector<int> R,P,X; …Run Code Online (Sandbox Code Playgroud)