2010-03-26 30 views
11

从Visual Studio 2010开始,遍历集合似乎会返回一个将数据作为“常量数据”而不是非常量进行解引用的迭代器。当从Visual Studio 2010开始取消引用迭代器时的const引用从Visual Studio 2010开始

下面的代码是一些在Visual Studio 2005上编译但不在2010上的例子(这是一个人为的例子,但清楚地说明了我们在自己的代码中发现的问题)。

在这个例子中,我有一个类与温度一起存储位置。我定义了比较运算符(并非全部,仅足以说明问题),只使用位置而不是温度。重点是对于我来说,如果位置相同,两个实例是相同的;我不在乎温度。

#include <set> 

class DataPoint 
    { 
    public: 
     DataPoint (int x, int y) : m_x(x), m_y(y), m_temperature(0) {} 
     void setTemperature(double t) {m_temperature = t;} 
     bool operator<(const DataPoint& rhs) const 
     { 
     if (m_x==rhs.m_x) return m_y<rhs.m_y; 
     else    return m_x<rhs.m_x; 
     } 
     bool operator==(const DataPoint& rhs) const 
     { 
     if (m_x!=rhs.m_x) return false; 
     if (m_y!=rhs.m_y) return false; 
     return true; 
     } 
    private: 
     int m_x; 
     int m_y; 
     double m_temperature; 
    }; 

typedef std::set<DataPoint> DataPointCollection; 

void main(void) 
{ 
DataPointCollection points; 

points.insert (DataPoint(1,1)); 
points.insert (DataPoint(1,1)); 
points.insert (DataPoint(1,2)); 
points.insert (DataPoint(1,3)); 
points.insert (DataPoint(1,1)); 

for (DataPointCollection::iterator it=points.begin();it!=points.end();++it) 
    { 
    DataPoint &point = *it; 
    point.setTemperature(10); 
    } 
} 

在主例程中,我有一个集合,我添加了一些要点。为了检查比较运算符的正确性,我多次添加具有相同位置的数据点。当写出集合的内容时,我可以清楚地看到集合中只有3个点。

for循环遍历该集合,并设置温度。逻辑上这是允许的,因为比较操作员没有使用温度。

此代码正确编译在Visual Studio 2005,但下面的行给出了Visual Studio 2010的编译错误(在for循环):

DataPoint &point = *it; 

给出的错误在于,它无法分配一个“const数据点”指向[非常量]“DataPoint &”。

如果您有比较运算符只比较数据成员的某些部分,那么在VS2010中似乎没有像样的(非肮脏的)代码编写方式。

可能的解决方案是:

  • 添加一个常量播到它给出了一个错误
  • 进行温度可变的线,使setTemperature一个const方法

但对我来说这两种解决方案看起来相当“脏”。

看起来C++标准委员会忽视了这种情况。或不?

什么是干净的解决方案来解决这个问题? 你们有没有遇到同样的问题,你是如何解决它的?

帕特里克

+1

http://connect.microsoft.com/VisualStudio/feedback/details/532300/std-set-t-iterator-and-std-set-t-const-iterator-are-the-同类型中断码 – mlvljr 2012-05-10 12:43:10

+1

尼斯链接。似乎我不是唯一一个找到它的人。 – Patrick 2012-05-10 14:09:16

+0

是的,我只是写了一些(现在很清楚)错误的STL ::设置代码,经过一小时的调试,这就是谷歌搜索,来到这里和那里:) – mlvljr 2012-05-10 21:11:06

回答

13

迭代器应该给你一个const引用(这就是标准说,它应该做的),因为改变所提及的事情会破坏集的基础数据结构的有效性 - 一组没有按” t“知道”你正在改变的领域实际上并不是关键的一部分。替代方法是通过删除和重新添加来进行更改,或者使用std :: map来代替。

+0

如果发现这个问题,同事。就个人而言,我会使用std :: map,但对我来说,它看起来像自定义比较运算符和集合在VS2010中不太合适。 – Patrick 2010-03-26 12:29:01

+4

自定义比较和集合只是很好,但可变数据类型和集合不。 – 2010-03-26 12:30:19

0

如果你不想删除和重新添加,因为尼尔建议你可以制作setTemperatureconstm_temperaturemutable

+0

正是我在我的问题中所说的。虽然这有效,但我仍然不觉得这是一个体面的解决方案。 – Patrick 2010-03-26 15:23:31

0

Set应该返回一个const迭代器,因为它不知道任何成员函数是否可以改变顺序。

看起来你真的想要一张地图,在那里你将你的不可变(x,y)键映射到一个变化的温度。

1

刚刚开始我们转换到2010年,这是我们一直面临的最大障碍。幸运的是,他们确实揭示了一些长期存在的问题,我们正在改变组成排序组合的一部分。

在其他情况下,我们的解决方案是使用mutable和declare方法作为const。当通过引用(指针或引用)将解引用的迭代器传递给一个函数时,如果它没有被改变,我们将该参数作为consst。

丹尼斯

相关问题