【问题标题】:Value of return is not same as value actually returned?返回值与实际返回值不同?
【发布时间】:2013-05-19 09:47:14
【问题描述】:

我有一个小错误让我大吃一惊。也许这很简单,但我完全迷失了。

我有一个基本的 POD struct:

    struct Data{
    bool isInvalid=false;
    vec3 *vector; //vec3 is another struct with x,y,z components
    Node*node;
    bool isFresh;
    unsigned int *form;
    };

我有一个函数:

  Data getData(){
    Data forReturn;
    //...populates the forReturn struct
    cout<<forReturn.vector->x; //logs correctly a value 
    return forReturn;
   }

cout 日志正确显示我的返回 Data 已被填充。但是当我从另一个函数调用这个函数时,就会出现不同的情况:

  Data newData=getData(); //logs as above
  cout<<newData.vector->x; //is empty!!

这是怎么回事?!我的日志输出并排显示这两行,因为它们紧随其后,但是发生了什么?这不是多线程的,所以变量和指针不应该在这两行之间改变!

【问题讨论】:

  • 你能显示Data的完整定义吗?
  • forReturn.vector 指向什么? BTW forReturn 不是指针,所以 forReturn-&gt;vector 不会编译。
  • Data 可能是struct Data * 的类型定义,还是类似的东西?如果是这样,你真的应该证明这一点,它从根本上改变了问题。
  • 显示填充forReturn-&gt;vector 的代码。理想情况下,展示一个可以编译和重现问题的最小程序。
  • @Fellowshee:现在你应该展示如何填充它

标签: c++


【解决方案1】:

如果这样写,本地数据 (forReturn) 在返回过程中被复制。因此,以正确的方式实现 Data-class 的复制结构至关重要(以正确的方式复制所有成员)

【讨论】:

  • ...//populates the forReturn struct 不将vector 指针关联到本地vec3 对象也很重要...
【解决方案2】:

除非我看到您拥有的真实代码,否则我无法确定,但我敢打赌,您的程序有未定义的行为,因为您正在取消引用 悬空指针。我相信在您的getData() 函数中,您让forReturn.vector 指向具有自动存储持续时间 的本地对象,该对象在从getData() 返回时被销毁,如下所示:

Data getData(){
    Data forReturn;
    vec3 myVector;
    // ...
    forReturn.vector = &myVector;
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    // ...
    cout<<forReturn.vector->x; // logs correctly a value 
    return forReturn;
}

在上面的示例中,我按值返回 Data 对象 forReturn,这意味着将调用隐式声明的移动构造函数(在 C++11 中)或复制构造函数(在 C++03 中)。

由于这些隐式生成的特殊成员函数执行数据结构成员的成员移动或复制,vector 指针 被复制,这意味着我返回的是 @ 类型的对象987654329@,其vector 指针指向的对象已经超出范围。

这是一个定时炸弹。一旦该指针被取消引用,“Boom”。请注意,“轰隆声”实际上可能是一个非常安静的爆炸 - 未定义行为意味着 任何事情 都可能发生,包括什么都没有发生。

【讨论】:

  • Scott Meyers 喜欢提到,未定义的行为 也可能意味着您的硬盘驱动器可能会被擦除。 :)
  • @Fellowshee: Right ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-23
  • 2021-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多