【问题标题】:STL iterators and 'const'STL 迭代器和 'const'
【发布时间】:2010-07-28 15:16:37
【问题描述】:

当我使用迭代器时,我有一个问题,似乎是某种隐式转换为 const。我不确定哪个代码是相关的(如果我这样做了,我可能不会问这个问题!)所以我会尽力说明我的问题。

typedef set<SmallObject> Container;              //not const

void LargeObject::someFunction() {               //not const
    Container::iterator it;                      //not const
    for (it = c.begin(); it != c.end(); ++it) {  //assume c is a "Container"
        (*it).smallObjectFunction();             //not a const function
    }
}

但是我总是收到以下错误:

error: passing 'const SmallObject' as 'this' argument of 'int SmallObject::smallObjectFunction()' discards qualifiers

但是,如果我将其转换为 ((SmallObject)(*it).smallObjectFunction();,那么我会删除错误消息。

我唯一能想到的就是以某种方式定义

bool operator< (const SmallObject &a) const;

以某种方式导致迭代器返回 const 对象。这里有任何帮助或解释吗?

【问题讨论】:

  • 能否请您发布SmallObject的实现?

标签: c++ iterator constants


【解决方案1】:

集合和映射根据排序条件保持元素的顺序。对于不破坏不变量的用户代码,映射的key 和集合中的整个元素必须是常量。您的问题是存储的元素不是SmallObject,而是const SmallObject

如果没有限制,您可以:

int init[] = { 1, 2, 3, 4, 5 };
std::set<int> values( init, init+5 );
std::copy( values.begin(), values.end(), 
   std::ostream_iterator<int>(std::cout, " "));
   // 1 2 3 4 5
*(values.find(3)) = 5; // luckily this does not work!
std::copy( values.begin(), values.end(), 
   std::ostream_iterator<int>(std::cout, " "));
   // 1 2 5 4 5 -- not in order!!!

问题不仅在于现在集合元素不按顺序排列,而且取决于树的构建方式,可能存在集合中存在但找不到的元素。

【讨论】:

  • 所以将smallObjectFunction函数设为const(如果可以的话)将解决问题
  • 我正在修改smallObjectFunction的某些情况下的对象。我在这里有什么选择?像我提到的那样施放它(目前正在做)?从集合中删除,编辑并重新插入(丑陋)?还有什么?
  • 正确的做法是将小对象取出,编辑然后插入。否则你可能会破坏set 所依赖的顺序和不变量,你会得到意想不到的结果。如果更改不影响顺序,那么您可以使用带有任何键的映射并修改值 - 这不是 const。
  • 在迭代过程中删除和插入对象会不会导致问题?
  • 在迭代时删除元素会导致问题。有不同的处理方式,一般来说,获取迭代器的副本,推进它,删除旧的副本。插入不会使迭代器无效,因此您可以随时插入,但最好将修改后的元素保存在不同的容器中,并在完成迭代后将它们添加到集合中(以避免访问新元素)。如果您遵循此路径,请注意可能会在循环结束之前结束堆栈并重新插入元素的异常。
【解决方案2】:

您的代码愚蠢,并且可以使用符合标准的 STL 实现干净地编译,这取决于您的 STL 实现做出的一些设计决策。 C++03 标准没有指定 set::iteratorsreference typedef 应该是什么(在我看来,它们应该是非常量引用)。所以继续做你所做的,但是插入一个 const_cast

const_cast<SmallObject&>(*it).smallObjectFunction();

它比擦除和重新插入更有效,更清晰。有关此问题的更广泛讨论,请查看 Herb Sutter 的“More Exceptional C++”中的第 8 条。

在这种情况下执行 const_cast 是完全安全的,而且风格也不错,只要确保不更改确定顺序的字段的值即可。如果类的接口很难验证你没有改变顺序,那么接口可能设计得不好。

【讨论】:

    【解决方案3】:

    您的 c 容器中的对象是 const 并且 smallObjectFunction 尝试修改对象值。

    【讨论】:

      猜你喜欢
      • 2012-01-28
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      • 1970-01-01
      • 2011-07-19
      • 2011-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多