简体   繁体   English

C ++标准:多集中的意外的const_iterator

[英]C++ Standard: Unexpected const_iterator in multiset

I recently ran into an odd issue where I'd get a const_iterator instead of the expected iterator when iterating through a multiset. 我最近碰到了一个奇怪的问题,我在迭代一个multiset时会得到一个const_iterator而不是预期的iterator It turned out to be a non-issue for MSVC but g++ gave me an error: 事实证明这对于MSVC来说不是问题,但g ++给了我一个错误:

error: invalid initialization of reference of type 'myPtr&' from expression of type 'const boost::shared_ptr' 错误:从'const boost :: shared_ptr'类型的表达式初始化'myPtr&'类型的引用无效

Relevant code: 相关代码:

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);
    }
}

Quite a bit of research revealed that is a problem with lots of previous discussion. 相当多的研究表明这是一个很多先前讨论的问题。 I found these relevant bits: 我找到了这些相关的部分:

My background knowledge and grasp on the issue is limited and thus I'd like to know whether the standard doesn't define this behavior well enough in which case g++ and MSVC implement the behavior to their liking or whether either g++ or MSVC deviate from a well-defined standard. 我对这个问题的背景知识和掌握是有限的,因此我想知道标准是否不能很好地定义这种行为,在这种情况下,g ++和MSVC可以根据自己的喜好实现行为,或者g ++或MSVC是否偏离了明确的标准。

Thanks in advance. 提前致谢。

The iterators for set and multiset were changed from the standard iterator/const iterator pair to just being const iterators. set和multiset的迭代器从标准的iterator / const迭代器对变为const迭代器。 The reason for this change was that they are ordered containers, and changing the element inside of an iterator can actually invalidate this ordering constraint. 这种更改的原因是它们是有序容器,更改迭代器内部的元素实际上可以使此排序约束无效。

The version of GCC you're testing against has made this change, the version of VC that you're using has not. 您正在测试的GCC版本已经进行了此更改,您正在使用的VC版本没有。 VC10 (and VC9 SP1, I believe) always return const_iterators from sets and multisets. VC10(和VC9 SP1,我相信)总是从集合和多集合中返回const_iterators。

23.2.4/6 of the latest draft of C++1x (n3000.pdf at the moment) says C ++ 1x最新草案的23.2.4 / 6(目前为n3000.pdf)说

For associative containers where the value type is the same as the key type, both iterator and const_iterator are constant iterators. 对于值类型与键类型相同的关联容器,iterator和const_iterator都是常量迭代器。

std::set and std::multi_set are the associative containers where the value type is the same as the key type. std :: set和std :: multi_set是关联容器,其值类型与键类型相同。

How to fool the compiler for std::set::iterator? 如何欺骗std :: set :: iterator的编译器?

I have struct 我有结构

struct _item {
  int a;
  int b;
  bool operator <(const _item& x) const {return a<x.a;}
};

I want change only member b (b is irrelevant for sorting in set, only member a is compared). 我只想更改成员b(b与集合中的排序无关,只比较成员a)。

std::set<_item> data;
std::set<_item>::iterator iter=data.begin();
iter->b=0;  // error !!!

Avada Kedavra ! Avada Kedavra!

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

Of course more C + + correctly 当然更多的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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM