为了测试,我创建了一个unordered_set并尝试遍历该集合。该集合拥有自己的类:
class Student {
private:
int matrNr;
string name;
public:
Student( const int& matrNr = 0, const string& name = "" )
: matrNr( matrNr ), name( name ) {}
void setNr( const int& matrNr ) {
this->matrNr = matrNr;
}
...
};
我插入了一些元素,并尝试在迭代过程中更改对象:unordered_set<Student, meinHash> meineHashTable;
meineHashTable.emplace( 12, "Fred" );
meineHashTable.emplace( 22, "Barney" );
meineHashTable.emplace( 33, "Wilma" );
for (int i = 0; i < meineHashTable.bucket_count(); i++) {
cout << "Bucketnummer: " << i << endl;
unordered_set<Student, meinHash>::local_iterator iter; // not constant?!?
if (meineHashTable.bucket_size( i ) > 0) {
for (iter = meineHashTable.begin( i ); iter != meineHashTable.end( i ); iter++) {
//const_cast<Student&>(*iter).setNr( 1234 ); //This does work
iter->setNr( 1234 ); //This does not work
}
}
else {
cout << "An empty Bucket" << endl;
}
}
我使用了local_iterator(而不是const_local_iterator),但仍然无法更改对象。由于某些原因,迭代器仍然引用常量对象。我现在的问题是:为什么会这样?如果普通迭代器引用const对象,则const和非const迭代器之间有什么区别?
经过VisualStudio 2013和minGW的测试。
在此先感谢您的帮助:-)
编辑:
哈希函子:
struct meinHash {
size_t operator()( const Student& s ) {
return s.getNr();
}
};
对于将来有相同问题的该主题的发现者,如果使用暴力更改matrNr,则以下示例输出:const_cast<Student&>(*iter).setNr( 5 );
并尝试显示它:unordered_set<Student, meinHash>::local_iterator iter = meineHashTable.find( 5 );
iter->display();
您可能会得到类似:最佳答案
set
和unordered_set
都具有只读 key 。很容易理解为什么会发生这种情况-如果更改关键值,则数据结构会将其归档在错误的位置,并且您将无法再找到它。
以您的示例为例,假设您的哈希函数只是返回了matrNr
字段。当哈希数更改时,对1234
的任何查找都会失败,因为该哈希存储桶中没有存储任何内容。
可以更改未使用哈希键的对象的某些部分,但这将导致难以跟踪错误。标准委员会决定通过制作整个键const来消除这种可能性。
有两种方法可以解决此限制。第一种是从值中拆分键,并改用map
或unordered_map
。第二种是从集合中删除该项目,然后在对其进行修改后将其重新插入。