返回值会发生啥?

Posted

技术标签:

【中文标题】返回值会发生啥?【英文标题】:What happens with return value?返回值会发生什么? 【发布时间】:2015-07-10 21:01:01 【问题描述】:

所以我在这个例子中有 2 个类:E,当它被销毁时打印一条消息 + 可以存储整数值T,它存储E 的实例并可以返回它通过方法

代码:

class E

public:
    E();
    ~E();
    int test;
;

E::E()
E::~E()

    std::cout << "E is destroyed" << std::endl;


///////////////////////////////////////////

class T

public:
    T();
    ~T();
    E data;
    E get();
;

T::T()
T::~T()
E T::get()

    return this->data;


///////////////////////////////////////////

int main()

    E e;
    e.test = 2;

    T t;
    t.data = e;

    E* e2;
          
        e2 = &(t.get());
        std::cout << "end of block" << std::endl;
    

    std::cout << e2->test;

运行我的代码的结果是:

E is destroyed
end of block

这意味着E 的某些实例在到达 的末尾之前被销毁

问题: 1.我做了一点实验。 e2 = &amp;(t.get()); 行中的 t.get() 值是否正确,因为它没有按值分配给任何变量? 2.如果这个值被破坏,那意味着e2指针无效。但是std::cout &lt;&lt; e2-&gt;test; 行仍然打印保存的整数值。指针是否仍然有效,或者这些数据只是偶尔停留在这个内存位置?

【问题讨论】:

是的,你有一个dangling pointer 指向一个超出范围的变量。在此之后尝试对该对象执行任何操作都是未定义的行为。 请注意,如果您的函数具有签名E&amp; T::get(),您将返回对仍在范围内的data 的引用,这样就可以了。问题是您按值返回了 E,这是一个立即被销毁的临时值。 @Cyber​​,是的,我就是这么想的,谢谢。我读过一些关于临时工的东西,但不确定这是否完全是关于我的情况。那么,我对此是否正确:如果临时通过值立即分配给某物,它肯定不会被销毁,是吗? 【参考方案1】:

默认情况下,释放的内存未设置为特定值。因此,它保留了它拥有的最后一个值。发生的情况是您的 t-> 数据 副本 的地址存储在 e2 中。然后,编译器释放所述副本,因为您不再使用它。因此,您可以调用析构函数。

但是,您确实将值 保存在内存中,因此您的指针仍然可以访问它们。 (但我猜想 valgrind 会吐出无效的读取。)

所以是的,您的指针确实无效,但它仍然可以访问数据。

重新措辞以合乎逻辑地回答您的问题:

1) 它是一个副本,并没有立即分配,因此被立即销毁。

2) 值存在于地址中,但地址被视为无效并可能导致内存问题(例如分段错误)

【讨论】:

【参考方案2】:

原始代码不会被 GCC 编译,因为函数

E T::get()

    return this->data;

返回值。当您在块中分配指针e2 = &amp;(t.get()); 时,它会生成data 的临时副本。从块中退出后,当您引用指针e2 时,它不再指向实际变量,因为临时变量超出了范围。所以为了纠正这个问题,你可以修改代码以返回对T类的data字段的引用:

E& T::get()

    return data;

之后当你再次运行代码时,你会看到:

end of block
2
E is destroyed
E is destroyed

注意这两个E is destroyed是因为有两个E实例,一个用于e,另一个用于t.data,因为代码t.data = e;会调用类的复制构造函数E。因此最终有两个E对象在程序退出时被破坏。

【讨论】:

以上是关于返回值会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的数组值会发生变化? [复制]

Oracle RawToHex 函数 - 如果返回值超过 varchar2 限制会发生啥?

为啥这个 bash 命令返回值会改变?

使用 BeautifulSoup 更改元素值会返回空元素

matlab命令中啥时候加分号

将浮点数分配给 long double 时,它​​的值会发生啥变化?