c++ - 使用基于范围的 for 循环和指针向量时的 C++ 错误
问题描述
在处理指针向量时,我偶然发现了这个奇怪的错误:
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)
意味着您在vec
迭代时正在创建每个元素的副本。&el
将是一个指向将在迭代结束时死亡的对象的指针。
你想用引用for (A& el: vec)
来遍历元素vec
。&el
然后将是指向内部实际元素的指针vec
。