【问题标题】:Iterator member behavior迭代器成员行为
【发布时间】:2010-08-06 20:13:39
【问题描述】:

我期待下面的第二个断言通过。我正在寻求您的帮助。

编辑:当我到处都有 poss 而不是某些地方的 poss_a 时,它不起作用。

#include <vector>
#include <cassert>

class Sampler
{
public:
 std::vector<int*> poss;
 std::vector<int*>::const_iterator poss_it;
 Sampler(std::vector<int*> poss_a) : poss(poss_a), poss_it(poss.begin())
 {
  assert( (poss[0]) == (*poss_it) ); //passes
 }
};

int main()
{
 int someInt;
 std::vector<int*> poss_a(1, &someInt);
 Sampler sampler(poss_a);
 assert( ((sampler.poss)[0]) == (*(sampler.poss_it)) ); //passes now

 return 0;
}

【问题讨论】:

  • 参数名和成员名不混用怎么样?
  • 如果您要编辑您的问题,请编辑它以更改变量和参数名称,以便更清楚什么是什么。
  • @Neil Butterworth -- 如果他这样做 -- 它会起作用(意思是,这是他的问题 -- 他正在用参数名称隐藏成员)
  • @Lou Quite - 我真的不知道他在这里想做什么,我已经删除了我认为我已经这样做的推测性答案。和往常一样,非常糟糕的问题得到了支持。叹息。
  • @drenami:如果在你改变它之后它失败了,你一定是不小心也改变了其他东西。我刚刚测试了代码。它会像您最初拥有的那样失败,但是当您进行我在回答中详述的更改时会通过。这是编译、运行并通过两项检查的程序的复制粘贴:pastebin.com/dPmtrm00

标签: c++ class pointers stl iterator


【解决方案1】:

初始化器列表中的poss_it(poss.begin()) 行从作为构造函数输入的 poss 中提取迭代器,而不是作为类字段的迭代器。

这是一个范围问题。当您在构造函数中时,这很好,因为您的迭代器是指向函数输入的指针。但是,当您离开构造函数时,它会指向内存中的同一位置,但现在您不知道该位置是什么。

您应该在构造函数中更改输入变量的名称。你想要一个这样做的人:

Sampler(std::vector<int*> input) : poss(input), poss_it(poss.begin())

而你现在的做法是这样的:

Sampler(std::vector<int*> input) : poss(input), poss_it(input.begin())

【讨论】:

    【解决方案2】:

    可能对覆盖实例变量的局部变量感到困惑,尝试

    #include <vector>
    #include <cassert>
    
    class Sampler
    {
    public:
        std::vector<int*> poss;
        std::vector<int*>::const_iterator poss_it;
        // THIS IS THE LINE I CHANGED
        Sampler(std::vector<int*> aPoss)    : poss(aPoss), poss_it(poss.begin())
        {
            assert( (poss[0]) == (*poss_it) ); //passes
        }
    };
    
    int main()
    {
        int someInt;
        std::vector<int*> poss(1, &someInt);
        Sampler sampler(poss);
        assert( ((sampler.poss)[0]) == (*(sampler.poss_it)) ); //fails
    
        return 0;
    }
    

    【讨论】:

    • 因为 this->poss_it 是参数的迭代器,而 this->poss 是参数的副本。在工作断言中,您将迭代器与索引的参数结果进行比较,而不是 this->poss。稍后您将迭代器与 this->poss 进行比较。解释起来很混乱,因为您在三个地方使用了变量名 poss —— 在构造函数中,参数隐藏了成员。
    【解决方案3】:

    您实际上是在调用未定义的行为,因为 sampler.poss_itstd::vector&lt;int*&gt; 对象的迭代器,该对象在第二个 assert 执行之前被破坏。

    问题就出来了:

    Sampler(std::vector<int*> poss) : poss(poss), poss_it(poss.begin())
    

    其中poss(poss) 的第一个poss 指的是Sampler 对象的poss 成员,poss(poss) 的第二个poss 指的是poss 参数,而@987654333 的poss @ 再次引用 poss 参数(不是 poss 成员)。 poss 参数在构造函数末尾超出范围,因此 poss 参数被破坏,这意味着 poss_it 迭代器不再有效。

    为避免此类问题,C++ 程序员几乎总是避免隐藏变量。此外,复制构造函数可能应该采用 const 引用(以避免潜在大对象的按值传递):

    Sampler(const std::vector<int*>& poss_) : poss(poss_), poss_it(poss.begin())
    

    【讨论】:

      猜你喜欢
      • 2020-03-10
      • 2011-03-24
      • 2014-02-02
      • 1970-01-01
      • 1970-01-01
      • 2019-06-06
      • 2021-08-17
      • 2011-05-26
      • 2018-08-11
      相关资源
      最近更新 更多