简体   繁体   English

STL迭代器和'const'

[英]STL iterators and 'const'

I have a problem with what appears to be some sort of implicit casting to const when I use iterators. 当我使用迭代器时,我有一个问题似乎是对const的某种隐式转换。 I'm not really sure which code is relevant (if I did I probably wouldn't be asking this question!) so I will try my best to illustrate my problem. 我不确定哪些代码是相关的(如果我这样做,我可能不会问这个问题!)所以我会尽力说明我的问题。

typedef set<SmallObject> Container;              //not const

void LargeObject::someFunction() {               //not const
    Container::iterator it;                      //not const
    for (it = c.begin(); it != c.end(); ++it) {  //assume c is a "Container"
        (*it).smallObjectFunction();             //not a const function
    }
}

However I always get the following error: 但是我总是得到以下错误:

error: passing 'const SmallObject' as 'this' argument of 'int SmallObject::smallObjectFunction()' discards qualifiers

However, if I cast it as ((SmallObject)(*it).smallObjectFunction(); then I get rid of the error message. 但是,如果我将其转换为((SmallObject)(*it).smallObjectFunction();那么我摆脱了错误消息。

The only thing I can figure is that somehow the definition of 我唯一可以想到的是,不知何故的定义

bool operator< (const SmallObject &a) const;

is somehow causing the iterator to return const objects. 以某种方式导致迭代器返回const对象。 Any help or explanation here? 这里有任何帮助或解释吗?

Sets and maps keep the elements in order according to the sort condition. 集合和贴图根据排序条件按顺序保留元素。 For user code not to break invariants, the key of the map and the whole element in the set must be constant. 对于不破坏不变量的用户代码,映射的key和集合中的整个元素必须是常量。 Your problem is that the stored element is not a SmallObject but a const SmallObject . 您的问题是存储的元素不是SmallObject而是const SmallObject

If this was not limited you could have: 如果这不受限制,您可以:

int init[] = { 1, 2, 3, 4, 5 };
std::set<int> values( init, init+5 );
std::copy( values.begin(), values.end(), 
   std::ostream_iterator<int>(std::cout, " "));
   // 1 2 3 4 5
*(values.find(3)) = 5; // luckily this does not work!
std::copy( values.begin(), values.end(), 
   std::ostream_iterator<int>(std::cout, " "));
   // 1 2 5 4 5 -- not in order!!!

The problem there is not only that now the set element would not be in order, but that depending on how the tree was built there could be elements that are present in the set but cannot be found. 问题不仅在于现在set元素不是有序的,而是根据树的构建方式,可能存在集合中存在但无法找到的元素。

Your code is not stupid and could compile cleanly with a conformant STL implementation, depending on some design decisions that your STL implementation made. 您的代码并不愚蠢, 可以使用符合标准的STL实现进行干净编译,具体取决于您的STL实现所做的一些设计决策。 The C++03 Standard does not specify what the reference typedef should be for set::iterators (in my opinion, they should be non-constant references). C ++ 03标准没有规定set :: iterators引用typedef应该是什么(在我看来,它们应该是非常量引用)。 So keep doing what you do, but insert a const_cast : 所以继续做你做的,但插入一个const_cast

const_cast<SmallObject&>(*it).smallObjectFunction();

It is more efficient and much clearer than erasing and re-inserting. 它比擦除和重新插入更有效,更清晰。 For a more extensive discussion of this problem, check out Item 8 in “More Exceptional C++” by Herb Sutter. 有关此问题的更广泛讨论,请查看Herb Sutter的“More Exceptional C ++”中的第8项。

It is perfectly safe to do a const_cast in this situation and it is not bad style, just make sure that you do not change the value of the fields that determine the order. 在这种情况下进行const_cast是完全安全的,并且风格也不错,只需确保不更改确定顺序的字段的值。 If the interface of the class makes it hard to verify that you do not change the order, then the interface is probably not well designed. 如果类的接口使得很难验证您没有更改顺序,那么接口可能没有很好地设计。

c容器中的对象是const,smallObjectFunction尝试修改对象值。

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

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