为什么这有效?返回 C++ 中的 const 引用

发布于 2024-08-20 17:56:56 字数 589 浏览 8 评论 0原文

我在玩弄 C++ 和 const 引用,并且很困惑为什么这段代码有效:

#include <iostream>

class A {
public:
    A() : a_(50) {}
    const int& getA() const { return a_; }
private:
    const int a_;
};

int main(int argc, char* argv[])
{
    A* a = new A();
    const int& var = a->getA();
    std::cout << var << std::endl;
    delete a;
    std::cout << var << std::endl;
}

结果:

50
50

这是我的想法:

var 存储对 a_ 的引用。
当a被删除时,a_也应该被删除。
当再次访问 var 时,它不再包含有效的引用,并且应该发生分段错误。

为什么这有效?我不相信我制作了临时副本。

I am fooling around with C++ and const references and am confused why this code works:

#include <iostream>

class A {
public:
    A() : a_(50) {}
    const int& getA() const { return a_; }
private:
    const int a_;
};

int main(int argc, char* argv[])
{
    A* a = new A();
    const int& var = a->getA();
    std::cout << var << std::endl;
    delete a;
    std::cout << var << std::endl;
}

Result:

50
50

Here are my thoughts:

var stores a reference to a_.
when a is deleted, a_ should also be deleted.
when var is accessed again, it no longer contains a valid reference and a segmentation fault should occur.

Why does this work? I do not believe I make a temporary copy.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

临走之时 2024-08-27 17:56:56

当您删除 a 时,访问 var 就成为您进入未定义行为领域的大门。

这是偶然的“工作”。 var 所指的空间不再属于您,但这次您成功地访问了它。它可能会导致分段错误、返回 50 以外的数字或重新格式化您的硬盘驱动器。

请记住,看似有效是未定义行为表现出来的一种可能方式。

The moment you deleted a, accessing var became your door into undefined behavior land.

It's "working" by chance. The space where var was one referring to is no longer yours, but you got away with accessing it, this time. It could have resulted in a segmentation fault, returned a number other than 50, or reformatted your hard drive.

Remember, seeming to work is one possible way undefined behavior can manifest itself.

于我来说 2024-08-27 17:56:56

删除对象并不会清除内存。该值将一直存在,直到内存被用于其他用途。所以它可能会工作一段时间......

一些 C++ 实现有一个“调试模式”,它为所有已删除的内存设置一个特定的值来检测这样的错误。

Deleting an object does not clear the memory. The value will still be there until the memory is used for something else. So it may work for a while....

Some C++ implementations have a "debug mode" that sets a particular value to all deleted memory to detect bugs like this.

燕归巢 2024-08-27 17:56:56

当您删除一个内存时,您将释放内存并允许后面的新内存覆盖它。在此之前,已删除对象内的所有变量仍在内存中,但可能随时被覆盖。

When you delete a you are freeing the memory and allowing a latter new to override it. Until then all the variables inside your deleted object are still in memory, but may be overridden at any time.

栀子花开つ 2024-08-27 17:56:56

由于 const 关键字的存在,这非常棘手。

确实,在这种情况下您可能正在读取未初始化的内存。对此的一些想法:

  1. 您没有使用调试模式:只要代码尚未经过测试,这通常不是一个好主意,但它留下了两个选项:
    • 释放模式内存管理器不会覆盖内存,因此您访问最后一个已知的地址,该地址仍然可以偶然工作
    • 或者整个操作已完全优化,因为编译器知道您没有更改该值,并且它无法从外部更改(尽管由于 C++ 中 const 正确性的限制,这可能不是真的)
  2. 您处于调试模式,但激活了优化,因此应用相同的参数
  3. _a< 的内容/code>,由于标记的 const 既不是堆分配的,也不是堆栈分配的,而是驻留在应用程序的 DATA 部分,因此引用可能确实仍然有效,不仅如此偶然。[编辑]:这只适用于static const 变量。

您可能会考虑编写自定义内存管理器或研究编译器的调试模式行为,因为这非常非常重要。例如,Visual Studio 将变量设置为 0xCDCCDCD。您还会在数组末尾发现有趣的值,例如 0xDEADC0DE

This is quite tricky because of the const keyword.

True, you could be reading uninitialized memory in this case. Some thoughts on that:

  1. You're not using debug mode: this is generally not a good idea as long as the code hasn't been tested, but it leaves two options:
    • The release mode memory manager does not overwrite the memory, so you acces the last known address, which still works by chance
    • OR The whole operation is completely optimized away because the compiler knows you didn't change the value and it couldn't change from the outside (though that might not be true due to the limitations of const correctness in C++)
  2. You are in debug mode, but have optimizations activated, so the same argument applies
  3. The contents of _a, since marked const are not heap-allocated nor stack allocated but reside in the DATA section of the application, so the reference might indeed be still valid, not only by chance. [EDIT]: This can only be true for static const variables.

You might consider writing a custom memory manager or research on the debug mode behaviour of your compiler, because this is very, very important. Visual Studio will set variables to 0xCDCDCDCD, for example. You will also find funny values such as 0xDEADC0DE at the end of arrays.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文