unordered_set非const迭代器

Mil*_*nia 9 c++ stl unordered-set c++11

出于测试目的,我创建了一个小的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;
    }
...
};
Run Code Online (Sandbox Code Playgroud)

我插入了一些元素并尝试在迭代期间更改对象:

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

}
Run Code Online (Sandbox Code Playgroud)

我使用了local_iterator(而不是const_local_iterator),但仍然无法更改对象.由于某些原因,迭代器仍然指向一个常量对象.

我现在的问题是:为什么会这样?如果普通迭代器引用const对象,那么const和非const迭代器之间有什么不同?

使用VisualStudio 2013和minGW进行测试.

在此先感谢任何帮助:-)

编辑:哈希仿函数:

struct meinHash {
    size_t operator()( const Student& s ) {
        return s.getNr();
    }
};
Run Code Online (Sandbox Code Playgroud)

对于具有相同问题的未来该主题的查找者,如果您使用暴力更改matrNr,则以下是一些示例输出:

const_cast<Student&>(*iter).setNr( 5 );
Run Code Online (Sandbox Code Playgroud)

并尝试显示它:

unordered_set<Student, meinHash>::local_iterator iter = meineHashTable.find( 5 );
iter->display();
Run Code Online (Sandbox Code Playgroud)

你可能会得到类似的东西:

Bucketnummer:0

一个空桶

Bucketnummer:1

Matrikelnummer:5

姓名:威尔玛

Bucketnummer:2

一个空桶

Bucketnummer:3

一个空桶

Bucketnummer:4

Matrikelnummer:5

姓名:弗雷德

Bucketnummer:5

一个空桶

Bucketnummer:6

Matrikelnummer:5

姓名:巴尼

Bucketnummer:7

一个空桶

//不想要的输出;-)

Matrikelnummer:-842150451

名称:

Mar*_*som 13

双方setunordered_set具有只读键.很容易理解为什么会出现这种情况 - 如果关键值发生变化,数据结构会将其归档到错误的位置,您将无法再找到它.

根据您的示例,假设您的哈希函数只返回该matrNr字段.当哈希值更改时,任何查找1234都将失败,因为该哈希桶中没有任何内容存储.

有可能更改未用于制作散列键的对象的某些部分,但这可能导致难以追踪错误.标准委员会决定通过制作整个密钥const来消除这种可能性.

围绕这种限制有两种方法.第一种是从值中拆分键并使用mapunordered_map替代.第二种是从集合中删除项目,并在修改后重新插入.


Ker*_* SB 7

他们看重的类型set<K>const K,而对于map<K, T>pair<const K, T>; 对于无序版本同样如此.

迭代器为您提供访问权限value_type &,并为其提供循环访问器const value_type &.如您所见,迭代器类型都不能"撤消"键的常量.

密钥不可变的原因是它构成了底层数据结构的组成部分; 更改密钥将需要一个非平凡的内部重新排列,这将导致各种问题(例如,非零计算复杂性(对于元素访问!),以及混淆迭代器排序).