unordered_set非const迭代器 [英] unordered_set non const iterator

查看:202
本文介绍了unordered_set非const迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了测试的目的,我创建了一个小的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 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); //这不工作
}

}
else {
cout< 空桶< endl;
}

}



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



我的问题:为什么是这样的?如果正常的迭代器引用一个const对象,const和非const迭代器有什么区别?



使用VisualStudio 2013和minGW测试。

感谢您提供任何帮助: - )



编辑:
Hash函数:

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

您可能会得到类似的结果:


Bucketnummer:0



空桶



Bucketnummer:1



Matrikelnummer:5



名称:Wilma



Bucketnummer:2



空桶



Bucketnummer:3



一个空桶



Bucketnummer:4



Matrikelnummer:5



名称:Fred



Bucketnummer:5



空桶



Bucketnummer:6



Matrikelnummer:5



p>

Bucketnummer:7



空桶



/不想要的输出; - )



Matrikelnummer:-842150451



名称:



解决方案

两个设置 unordered_set 有只读密钥。很容易看出为什么会是这种情况 - 如果关键的价值是改变,数据结构将它提交在错误的位置,你将不能再找到它。



根据你的例子,假设你的哈希函数返回 matrNr 字段。当散列数变化时,对 1234 的任何查找都将失败,因为该散列桶中没有存储任何内容。



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



有两种方法可以解决这个限制。第一种是从该值拆分键,然后使用映射 unordered_map 。第二个是从集合中删除项目,并在修改之后重新插入。


For testing purposes I created a little unordered_set and tried to iterate over the set. The set holds an own class:

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

I inserted some elements and tried to change the objects during iteration:

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

}

I used a local_iterator (and not the const_local_iterator) but still I can't change the objects. For some reasons the iterator refers still to a constant object.

My question now: why is this so? If the normal iterator refers to a const object, what is the different between the const and the non-const iterator?

Tested with VisualStudio 2013 and minGW.

Thanks in advance for any help :-)

EDIT: The Hash functor:

struct meinHash {
    size_t operator()( const Student& s ) {
        return s.getNr();
    }
};

For finders of this topic in the future who have the same question, here is some example output if you change the matrNr with violent:

const_cast<Student&>(*iter).setNr( 5 );

and try to display it:

unordered_set<Student, meinHash>::local_iterator iter = meineHashTable.find( 5 );
iter->display();

you may get something like:

Bucketnummer: 0

An empty Bucket

Bucketnummer: 1

Matrikelnummer: 5

Name: Wilma

Bucketnummer: 2

An empty Bucket

Bucketnummer: 3

An empty Bucket

Bucketnummer: 4

Matrikelnummer: 5

Name: Fred

Bucketnummer: 5

An empty Bucket

Bucketnummer: 6

Matrikelnummer: 5

Name: Barney

Bucketnummer: 7

An empty Bucket

//The not wanted output ;-)

Matrikelnummer: -842150451

Name:

解决方案

Both set and unordered_set have read-only keys. It's easy to see why this is the case - if the key value were to change, the data structure would have it filed in the wrong spot and you wouldn't be able to find it anymore.

Per your example, suppose your hash function simply returned the matrNr field. When the hash number changes, any lookup for 1234 will fail because there's nothing stored in that hash bucket.

It could be possible to change some part of the object that is not used in making the hash key, but that would lead to possible hard to track down bugs. The standards committee decided to eliminate that possibility by making the entire key const.

There are two ways around this restriction. The first is to split the key from the value and use a map or unordered_map instead. The second is to remove the item from the set and reinsert it after it's modified.

这篇关于unordered_set非const迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆