【问题标题】:C++ bug when using range-based for loop and vector of pointers [duplicate]使用基于范围的 for 循环和指针向量时的 C++ 错误 [重复]
【发布时间】:2020-03-09 05:26:18
【问题描述】:

在处理指针向量时,我偶然发现了这个奇怪的错误:

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);
      |     ^

(错误也在 ARCH 上使用 GCC 9.2.0 重现,但 Apple clang 11.0.0 给出了预期的输出)

预期输出:

$ ./mwe
42

实际输出:

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

我是否无意中在某处引入了未定义行为?如果没有,为什么这不能按预期工作?

【问题讨论】:

  • for (A el: vec) - 你遍历vector元素的副本。然后获取该副本的地址,将其 push_back 到第二个向量中,然后丢弃副本对象。
  • 那个副本很好,但我投票关闭作为一个简单的印刷错误。
  • 这不是印刷错误。

标签: c++ pointers gcc vector


【解决方案1】:

for (A el: vec) 表示您在迭代时创建了vec 中每个元素的副本。 &amp;el 将是一个指向将在迭代结束时死亡的对象的指针。

您想使用for (A&amp; el: vec) 通过引用迭代vec 的元素。然后&amp;el 将成为指向vec 中实际元素的指针。

【讨论】:

  • 我很好奇为什么它可以像我预期的那样在 clang 中工作。
  • @orfeas:你有未定义的行为。任何事情都可能发生,包括看起来可以运行的程序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-04
  • 2011-08-08
  • 2018-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多