Dan*_*age 2 c++ scope for-loop vector
以下虚拟程序模仿我正在排除故障的另一个程序的行为.
#include <iostream>
#include <vector>
class A
{
public:
std::vector<int> data;
void DoTheThing()
{
while (data.size() < 10) {
data.push_back(1);
}
}
};
class B
{
public:
std::vector<A> objs;
B()
{
A one, two, three;
objs.push_back(one);
objs.push_back(two);
objs.push_back(three);
}
void DoTheThing()
{
for (auto obj: objs) {
obj.DoTheThing();
std::cout << "DEBUG length during=" << obj.data.size() << std::endl;
}
}
};
int main()
{
B b;
b.DoTheThing();
for (auto obj : b.objs) {
std::cout << "DEBUG length after=" << obj.data.size() << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
我编译并运行为:
$ g++ -Wall --std=c++11 -o test test.cpp
$ ./test
DEBUG length during=10
DEBUG length during=10
DEBUG length during=10
DEBUG length after=0
DEBUG length after=0
DEBUG length after=0
$
Run Code Online (Sandbox Code Playgroud)
出于某种原因,状态A物体b的objs向量之间改变b.DoTheThing()呼叫和后面的print语句.我的问题是发生了什么?A对象data向量是否以某种方式超出范围并被删除,或者可能是整个A对象?这似乎是一个范围问题 - 可能甚至是一个简单的问题 - 但它已经足够长了,因为我用C++编程我不确定.data在调用b.DoTheThing()其他方法后,如何使向量的内容保持不变?
"出于某种原因
A,b中对象的状态objsvector在b.DoTheThing()调用和后续的打印语句之间发生了变化.我的问题是发生了什么? "
void DoTheThing()
{
for(auto obj : objs)
// ^^^^^^^ receive by value due to implicit copy
Run Code Online (Sandbox Code Playgroud)
您实际上正在单独复制objs到单个临时objs中.那些临时工作在B::DoThething()完成后被摧毁.要避免副本,请使用参考:
for(auto& obj : objs)
// ^^^^^^^ receive by reference
Run Code Online (Sandbox Code Playgroud)
对于类似的循环也是如此main().
真正的问题可能是:"如何避免此类事故?"
如果你能负担得起,那么制作复制构造函数explicit以避免隐式复制:
class A {
public:
A () = default;
explicit A(const A&) = default; // implicit copy is avoided
A (A&&) = default; // to avoid RVO related issues
...
};
Run Code Online (Sandbox Code Playgroud)
这是一个演示,它演示了如何explicit生成编译错误以捕获for循环中的问题,这意外地进行了复制.
将explicit带来它自己的语法限制.其中一些可以解决,一些不能解决.请参阅以下问题以解决1个问题(及其解决方法):
'explicit'关键字对返回值优化(RVO)的影响是什么?