【问题标题】:Changing a classes member through an iterator通过迭代器更改类成员
【发布时间】:2010-08-12 13:14:11
【问题描述】:

我正在学习 C++,但无法解决这个问题:

我有一个简单的 A 类

class A {
private:
    int ival;
    float fval;

public:
    A(int i = 0, float f = 0.0) : ival(i), fval(f) { }
    ~A(){ }
    void show() const { 
        cout << ival << " : " << fval << "\n";
    }
    void setVal(int i) {
        ival = i;
    }

    //const getters for both ival and fval

    //used for the default "lesser"
    friend bool operator<(const A& val1, const A& val2) {
        return val1.ival < val2.ival ? true : false;;
    }
}

然后我有一个常规的set&lt;A&gt; myset,它在循环中被insert(A(2, 2.2)); 填充。

迭代获取所有值不是问题,但我想在此迭代中修改值:

for(set<A>::iterator iter = set3.begin(); iter != set3.end(); iter++) {
    iter->setVal(1);
}

我认为这应该是可行的,就像您在 Java 中的 foreach 循环中那样。编译时我得到error: passing ‘const A’ as ‘this’ argument of ‘void A::setVal(int)’ discards qualifiers。

查看 STL 集的来源,我发现 begin() 只能作为 const 方法使用,我认为这可能是问题所在。在 setVal() 方法上乱用 const 总是会出现同样的错误,而且没有多大意义,因为我想修改 A 的值。

这是用循环更改一堆A 的值的错误方法吗?

【问题讨论】:

  • +1 因为看起来你真的是自己先搜索的,当你学到新东西时这总是一件好事。
  • 请注意val1.ival &lt; val2.ival ? true : false 与val1.ival &lt; val2.ival 相同。
  • @Pedro:谢谢,既然你这么说了,这很明显,但我自己看不到。

标签: c++ stl iterator constants


【解决方案1】:

STL 集不允许您更改它存储的值。它通过迭代器返回对象的副本(不是集合中的实际副本)来实现这一点。

set 这样做的原因是因为它使用

如果您需要更新集合,请删除旧值并添加新值。

编辑:刚刚检查了 SGI STL 的源代码,它说:

 typedef typename _Rep_type::const_iterator iterator;

所以,一个 set::iterator 只是一个 set::const_iterator

【讨论】:

  • 这是否意味着我只是在尝试使用一组而不是使用另一个容器时运气不好?这适用于矢量或列表还是...?
  • 您的意思是 const&,而不是副本。如果是副本,则不会是 const
  • @DrColossos 它适用于任何无序容器(列表、向量、unordered_set、...)
  • 我已经使用 set 实现实际制作了副本,因此强制转换 constness 对您没有帮助。你必须假设你不能通过演员来解决这个问题。
  • 如果一个实现返回了密钥的副本,那么它将是不合规的。另请注意,您不能,不得尝试使用 const-cast 修改对象,因为这会破坏设置的不变量。之前在 SO 中已经多次询问过这个问题。
【解决方案2】:

从this page看来,begin()似乎是存在的,也是一个非常量的方法。

也许您的集合作为 const 引用传递到方法中?

编辑

引用的页面错误。正如 Scharron 所说,对于有序容器,没有非 const begin()(或 end())方法。

我会通知网站他们的错误(这不是他们第一次犯的错误;))

【讨论】:

  • 不(至少我不这么认为?)。我使用set&lt;A&gt; myset;,而不是像我上面描述的那样添加A。
  • 我自己知道这个页面,很棒的资源! buf如果说源码中的定义是const,那么非constbegin()从哪里来?
  • 这是一个错误。 iterator 和 const_iterator 在有序容器上是相同的类型(因此只有一个 begin() const 和 end() const 方法)
  • @DrColossos & @Scharron:这看起来确实是个错误。刚试过,没有非常量的begin()方法。或者至少,我的编译器不知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-02
  • 1970-01-01
  • 2017-12-03
  • 1970-01-01
  • 2013-07-07
  • 2019-01-16
  • 1970-01-01
相关资源
最近更新 更多