使用基于范围的指针循环和向量时的C ++错误

时间:2019-11-13 12:01:34

标签: c++ pointers gcc vector

在弄乱指针矢量时,我偶然发现了这个奇怪的错误:

mwe.cpp

#include <iostream>
#include <vector>

class A {
  public:
    int x = 42; // making this unsigned causes output to be only positive
    int y;      // removing this makes bug disappear
};

class B {
  public:
    B(std::vector<A *> pt_vec) {
      std::cout << pt_vec[0]->x << std::endl;
    };
};

int main() {
  std::vector<A *> pt_vec;

  A a;                 //  these 3 lines can
  std::vector<A> vec;  //  be replaced with
  vec.push_back(a);    //  std::vector<A> vec {A()};
                       //  the bug will still appear

  for (A el: vec) {         // doing this without for (or
    pt_vec.push_back(&el);  // with iterators/good ol' for)
  }                         // makes bug disappear

  B b = B(pt_vec);

  //exit(1);    // uncommenting this makes bug disappear
}

如何复制:

$ gcc --version
gcc (Gentoo 9.2.0-r2 p3) 9.2.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ -O0 -Wall -Wpedantic mwe.cpp -o mwe
mwe.cpp: In function ‘int main()’:
mwe.cpp:27:5: warning: variable ‘b’ set but not used [-Wunused-but-set-variable]
   27 |   B b = B(pt_vec);
      |     ^

(Bug在ARCH上也与GCC 9.2.0一起复制,但是Apple clang 11.0.0给出了预期的输出)

预期输出:

$ ./mwe
42

实际输出:

$ ./mwe 
1533476528
$ ./mwe
-1607700816
$ ./mwe
<insert random huge number here>

我是否会在不经意间引入未定义行为?如果没有,为什么这不能按预期工作?

1 个答案:

答案 0 :(得分:4)

for (A el: vec)表示您正在迭代时在vec中创建每个元素的副本。 &el将是指向将在迭代结束时消失的对象的指针。

您想使用for (A& el: vec)通过引用遍历vec的元素。 &el将成为vec内部实际元素的指针。