我最近碰到了一个奇怪的问题,我在迭代多重集时得到const_iterator
而不是预期的iterator
。事实证明这对于MSVC来说不是问题,但g ++给了我一个错误:
错误:初始化无效 'myPtr&'类型的参考从 'const的类型的表达式 升压:: shared_ptr的'
相关代码:
typedef std::multiset<myPtr> myList;
myList _mystuff;
void tick(float dt)
{
for (myList::iterator i = _mystuff.begin(); i != _mystuff.end(); ++i)
{
myPtr &mine = *i; // g++ problem here, not for MSVC
// const myPtr &mine = *i; works fine for g++
mine->tick(dt);
}
}
相当多的研究表明,这是很多先前讨论的问题。我发现了这些相关的部分:
我对这个问题的背景知识和掌握是有限的,因此我想知道标准是否不能很好地定义这种行为,在这种情况下,g ++和MSVC可以根据自己的喜好实现行为,或者是g ++还是MSVC偏离明确的标准。
提前致谢。
答案 0 :(得分:16)
set和multiset的迭代器从标准迭代器/ const迭代器对更改为只是const迭代器。这种改变的原因是它们是有序容器,更改迭代器内部的元素实际上可以使这个排序约束无效。
您正在测试的GCC版本已经进行了此更改,您正在使用的VC版本没有。 VC10(和VC9 SP1,我相信)总是从集合和多集合中返回const_iterators。
23.2.4 / 6最新的C ++ 1x草案(目前为n3000.pdf)说
对于关联容器,其中 值类型与键相同 type,iterator和const_iterator 是常数迭代器。
std :: set和std :: multi_set是关联容器,其值类型与键类型相同。
答案 1 :(得分:1)
如何欺骗std :: set :: iterator的编译器?
我有结构
struct _item {
int a;
int b;
bool operator <(const _item& x) const {return a<x.a;}
};
我只想更改成员b(b与集合中的排序无关,只比较成员a)。
std::set<_item> data;
std::set<_item>::iterator iter=data.begin();
iter->b=0; // error !!!
struct _item {
int a;
int b;
_item* self;
_item() {self=this;}
bool operator <(const _item& x) const {return a<x.a;}
};
iter->self->b=0; // Success !! Tested on VC10
当然更多C ++正确
struct _item {
int a;
int b;
private:
_item* self;
public:
_item() {self=this;}
bool operator <(const _item& x) const {return a<x.a;}
int& bReference() const {return self->b;}
};
std::set<_item> items;
std::set<_item>::iterator iter=items.begin();
iter->bReference()=0; // Success !! Tested on VC1