为了测试,我创建了一个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();
您可能会得到类似:

最佳答案

setunordered_set都具有只读 key 。很容易理解为什么会发生这种情况-如果更改关键值,则数据结构会将其归档在错误的位置,并且您将无法再找到它。

以您的示例为例,假设您的哈希函数只是返回了matrNr字段。当哈希数更改时,对1234的任何查找都会失败,因为该哈希存储桶中没有存储任何内容。

可以更改未使用哈希键的对象的某些部分,但这将导致难以跟踪错误。标准委员会决定通过制作整个键const来消除这种可能性。

有两种方法可以解决此限制。第一种是从值中拆分键,并改用mapunordered_map。第二种是从集合中删除该项目,然后在对其进行修改后将其重新插入。

07-24 09:45
查看更多