c++ - 为什么在方法范围完成后 vector 内容会发生变化?

标签 c++ for-loop vector scope

以下虚拟程序模仿我正在排除故障的另一个程序的行为。

#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;
    }
}

我编译并运行为:

$ 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
$

由于某些原因,bobjs vector 中的 A 对象的状态在 b.DoTheThing( ) 调用和后续的打印语句。我的问题是发生了什么A 对象 data vector 是否超出范围并被删除,或者可能是整个 A 对象?这似乎是一个范围界定问题——甚至可能是一个微不足道的简单问题——但自从我用 C++ 编程以来它已经足够长了,我不确定。在其他方法中调用 b.DoTheThing() 后,如何使 data vector 的内容保持不变?

最佳答案

"For some reason the state of the A objects in b's objs vector is changing between the b.DoTheThing() call and the subsequent print statements. My question is what is happening?"

void DoTheThing()
{
  for(auto obj : objs)
   // ^^^^^^^ receive by value due to implicit copy

您实际上是在将 objs 单独复制到单独的临时 obj 中。 B::DoThething() 完成后,这些临时对象将被销毁。为避免复制,请使用引用:

  for(auto& obj : objs)
   // ^^^^^^^ receive by reference

main() 中的类似循环也是如此。


真正的问题可以是:“如何避免此类事故?”

如果你负担得起,那么将复制构造函数设为显式以避免隐式复制:

class A {
public:
  A () = default;      
  explicit A(const A&) = default;  // implicit copy is avoided
  A (A&&) = default;  // to avoid RVO related issues
  ...
};

这是一个demo ,它显示了 explicit 如何生成编译错误 以捕获意外复制的 for 循环中的问题。


explicit 带来了它自己的语法限制。其中有些可以解决,有些则不能。请参阅以下问题以了解 1 个此类问题(及其解决方法):

What is the effect of 'explicit' keyword on the Return Value Optimization (RVO)?

关于c++ - 为什么在方法范围完成后 vector 内容会发生变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38968068/

相关文章:

java - 使用 jobjectarray 中的参数调用 NewObject 方法 jni

vb.net - 使用 vb.net 迭代组合框控件的值

python - 在 python pandas 中通过索引减去数据帧(python pandas)的行的最有效方法是什么

c++ - 根据不同函数排序的 std::vectors 的交集

c++ - 射线平面求交方向 vector

c++ - 为什么聚合推导中不支持大括号初始化列表但支持大括号省略?

c++ - 如何格式化我的函数以调用模板类?

python - For 循环子集化的 pandas 数据帧

c++ - 将 const* 存储在 const vector 中

c++ - 在 typedef 中使用相同的名称并从命名空间中使用