遍历set容器时,不能修改容器元素的状态
2011-10-08 17:45
225 查看
// complex_number.h
#pragma once
class ComplexNumber
{
public:
ComplexNumber(double real, double virt);
bool operator < (const ComplexNumber& other) const;
double real() const;
double virt() const;
void print();
private:
double m_real;
double m_virt;
int m_count;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////
// complex_number.cpp
#include "complex_number.h"
#include <iostream>
using namespace std;
ComplexNumber::ComplexNumber(double real, double virt)
: m_real(real)
, m_virt(virt)
, m_count(0)
{
// do nothing
}
double ComplexNumber::real() const
{
return m_real;
}
double ComplexNumber::virt() const
{
return m_virt;
}
bool ComplexNumber::operator <(const ComplexNumber &other) const
{
if (m_real < other.real())
{
return true;
}
else if (m_virt < other.virt())
{
return true;
}
return false;
}
void ComplexNumber::print()
{
cout << "(real,virt): (" << this->m_real << "," << this->m_virt << ")" << endl;
++ this->m_count;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// main.cpp
#include "complex_number.h"
#include <set>
#include <iostream>
using namespace std;
int main()
{
set<ComplexNumber> complex_set;
complex_set.insert(ComplexNumber(1,1));
complex_set.insert(ComplexNumber(2,3));
set<ComplexNumber>::iterator iter = complex_set.begin();
for (; iter != complex_set.end(); ++ iter)
{
iter->print();
}
return 0;
}
1. 在visual studio环境下,编译顺利通过,但在g++环境下,编译报错:
[root@localhost test]# make
g++ -I . -I ../global -I ../ -g -c -o complex_number.o complex_number.cpp
g++ -I . -I ../global -I ../ -g -c -o main.o main.cpp
main.cpp: In function 'int main()':
main.cpp:20: error: passing 'const ComplexNumber' as 'this' argument of 'void ComplexNumber::print()' discards qualifiers
2. 原因在于set容器是靠容器元素的operator<来进行遍历的。如果在遍历的时候有操作改变里元素内部状态,可能会引起set容器元素顺序发生变化,因此g++编译报错。即使改变的成员不影响operator<,g++编译器也无法得知(而vc编译器在这点上做得比较好)。
3. 因此set容器遍历的时候,一定不要用迭代器去使用能改变容器元素状态的操作,而要用声明为const的操作,可用const_iterator来遍历保证。
修改后的代码如下,可正常编译通过。
// complex_number.h
#pragma once
class ComplexNumber
{
public:
ComplexNumber(double real, double virt);
bool operator < (const ComplexNumber& other) const;
double real() const;
double virt() const;
void print() const;
private:
double m_real;
double m_virt;
// int m_count;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////
// complex_number.cpp
#include "complex_number.h"
#include <iostream>
using namespace std;
ComplexNumber::ComplexNumber(double real, double virt)
: m_real(real)
, m_virt(virt)
, m_count(0)
{
// do nothing
}
double ComplexNumber::real() const
{
return m_real;
}
double ComplexNumber::virt() const
{
return m_virt;
}
bool ComplexNumber::operator <(const ComplexNumber &other) const
{
if (m_real < other.real())
{
return true;
}
else if (m_virt < other.virt())
{
return true;
}
return false;
}
void ComplexNumber::print() const
{
cout << "(real,virt): (" << this->m_real << "," << this->m_virt << ")" << endl;
// ++ this->m_count;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// main.cpp
#include "complex_number.h"
#include <set>
#include <iostream>
using namespace std;
int main()
{
set<ComplexNumber> complex_set;
complex_set.insert(ComplexNumber(1,1));
complex_set.insert(ComplexNumber(2,3));
set<ComplexNumber>::const_iterator iter = complex_set.begin();
for (; iter != complex_set.end(); ++ iter)
{
iter->print();
}
return 0;
}
#pragma once
class ComplexNumber
{
public:
ComplexNumber(double real, double virt);
bool operator < (const ComplexNumber& other) const;
double real() const;
double virt() const;
void print();
private:
double m_real;
double m_virt;
int m_count;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////
// complex_number.cpp
#include "complex_number.h"
#include <iostream>
using namespace std;
ComplexNumber::ComplexNumber(double real, double virt)
: m_real(real)
, m_virt(virt)
, m_count(0)
{
// do nothing
}
double ComplexNumber::real() const
{
return m_real;
}
double ComplexNumber::virt() const
{
return m_virt;
}
bool ComplexNumber::operator <(const ComplexNumber &other) const
{
if (m_real < other.real())
{
return true;
}
else if (m_virt < other.virt())
{
return true;
}
return false;
}
void ComplexNumber::print()
{
cout << "(real,virt): (" << this->m_real << "," << this->m_virt << ")" << endl;
++ this->m_count;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// main.cpp
#include "complex_number.h"
#include <set>
#include <iostream>
using namespace std;
int main()
{
set<ComplexNumber> complex_set;
complex_set.insert(ComplexNumber(1,1));
complex_set.insert(ComplexNumber(2,3));
set<ComplexNumber>::iterator iter = complex_set.begin();
for (; iter != complex_set.end(); ++ iter)
{
iter->print();
}
return 0;
}
1. 在visual studio环境下,编译顺利通过,但在g++环境下,编译报错:
[root@localhost test]# make
g++ -I . -I ../global -I ../ -g -c -o complex_number.o complex_number.cpp
g++ -I . -I ../global -I ../ -g -c -o main.o main.cpp
main.cpp: In function 'int main()':
main.cpp:20: error: passing 'const ComplexNumber' as 'this' argument of 'void ComplexNumber::print()' discards qualifiers
2. 原因在于set容器是靠容器元素的operator<来进行遍历的。如果在遍历的时候有操作改变里元素内部状态,可能会引起set容器元素顺序发生变化,因此g++编译报错。即使改变的成员不影响operator<,g++编译器也无法得知(而vc编译器在这点上做得比较好)。
3. 因此set容器遍历的时候,一定不要用迭代器去使用能改变容器元素状态的操作,而要用声明为const的操作,可用const_iterator来遍历保证。
修改后的代码如下,可正常编译通过。
// complex_number.h
#pragma once
class ComplexNumber
{
public:
ComplexNumber(double real, double virt);
bool operator < (const ComplexNumber& other) const;
double real() const;
double virt() const;
void print() const;
private:
double m_real;
double m_virt;
// int m_count;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////
// complex_number.cpp
#include "complex_number.h"
#include <iostream>
using namespace std;
ComplexNumber::ComplexNumber(double real, double virt)
: m_real(real)
, m_virt(virt)
, m_count(0)
{
// do nothing
}
double ComplexNumber::real() const
{
return m_real;
}
double ComplexNumber::virt() const
{
return m_virt;
}
bool ComplexNumber::operator <(const ComplexNumber &other) const
{
if (m_real < other.real())
{
return true;
}
else if (m_virt < other.virt())
{
return true;
}
return false;
}
void ComplexNumber::print() const
{
cout << "(real,virt): (" << this->m_real << "," << this->m_virt << ")" << endl;
// ++ this->m_count;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// main.cpp
#include "complex_number.h"
#include <set>
#include <iostream>
using namespace std;
int main()
{
set<ComplexNumber> complex_set;
complex_set.insert(ComplexNumber(1,1));
complex_set.insert(ComplexNumber(2,3));
set<ComplexNumber>::const_iterator iter = complex_set.begin();
for (; iter != complex_set.end(); ++ iter)
{
iter->print();
}
return 0;
}
相关文章推荐
- map常用成员(关联容器)----创建map<主键,主键对应的值>,增insert,删erase,改查找find,然后修改second,遍历iterator,获取元素个数size,判空empty
- 容器 Iterator 遍历时安全的删除元素
- 边遍历容器边删除容器元素——适用于…
- 用友uap开发nc65主子表修改按钮不能跳转到修改状态
- dialog module (4)修改屏幕上某个或某几个元素的状态
- 子元素浮动父容器高度不能自适应的CSS解决方法
- 使用 forEachIndexed 带下标遍历 list;这样我们可以使用 forEach 来修改 list 的元素了
- 解决 jquery dialog 弹框destroy销毁方法不能把弹出元素设置成初始状态
- 遍历打印容器元素的函数模板
- js:遍历容器中的元素
- Java 遍历容器中元素的方法总结
- ConcurrentModificationException遍历集合时,不能对集合进行修改操作
- 在for循环遍历列表的过程中不能删除列表中的元素
- auto_ptr智能指针不能作为STL标准容器的元素
- matlab 条件删除某元胞元素时不能使用for,而应该使用while进行遍历所有元胞
- stl容器遍历删除元素
- java for-each本质--不能增加和删除,但是可以修改当前元素
- javascript 常见数组操作( 1、数组整体元素修改 2、 数组筛选 3、jquery 元素转数组 4、获取两个数组中相同部分或者不同部分 5、数组去重并倒序排序 6、数组排序 7、数组截取slice 8、数组插入、删除splice(需明确位置) 9、数组遍历 10、jQuery根据元素值删除数组元素的方)
- Iterator为什么不能对容器的进行添加或修改操作(可以删除)
- IE float浮动 子元素不能撑开父容器 解决办法