gpt4 book ai didi

c++ - 了解 C++ 如何返回引用并绑定(bind)到引用

转载 作者:行者123 更新时间:2023-12-01 14:33:27 27 4
gpt4 key购买 nike

#include <iostream>

class A {
public:
int x = 0;
};

A& a_returner() {
A a;
return a;
}

int main()
{
A& a = a_returner();
std::cout << a.x << std::endl;
}

在此代码中,a_returner() 返回对堆栈 中变量a 的引用。如果我们这样调用:

A a = a_returner();

这不是问题,因为我们只是复制返回的 A 对象。但是,我们都在 a_returner 中返回一个引用并绑定(bind)到一个引用。

问题是:为什么这有效? A 存在于 a_returner 的栈中。

编译器确实给出了

Warning: reference to local variable `a` returned

但是程序成功打印了0。我认为访问从 a_returner 返回的 a 会访问无效数据。

最佳答案

您对“有效”的含义有错误的心理模型。

问题中的代码不起作用。当您尝试时它没有崩溃并且结果是您所期望的,但这并不意味着(在 C++ 中)一切都很好。

你刚刚发现的是“未定义行为”最糟糕的一面,即当你在 C++ 中犯了一个错误(例如返回对堆栈上对象的引用)任何事情都可能发生,包括什么都没有,代码可能 显然按照您的意愿工作。

代码仍然无法正常工作,并且在开发周期的后期会出现可怕的错误。

C++ 的主要哲学基础是程序员不犯错误,因此您得到的不是捕捉错误的“运行时错误角度”,而是“未定义的行为守护进程”,如果出现错误,程序可以做任何它想做的事情,包括临时隐藏问题,以便以后更加努力地反击。因此,在其他语言中,例如,当你超出数组的边界时,你会得到一个运行时错误,而在 C++ 中,你会得到未定义的行为,原因是假设 C++ 程序员永远不会超出数组的边界,并且没有浪费时间检查这一点。

回顾一下:在 C++ 中,如果程序崩溃,您就知道代码有问题...如果程序确实没有崩溃并且结果如您所愿,您仍然不能 确保代码是正确的(即使是您作为输入提供的单个案例也是如此)。

许多 C++ 学习者和一些自封为 C++“专家”的人认为崩溃是敌人,您应该防止崩溃(或者更糟的是吸收并吞下它们以继续运行)。实际上恰恰相反,崩溃是你的 friend ,程序错误是敌人。问题是 C++ 崩溃的频率不够高,有时应该崩溃的错误代码没有崩溃(就像你的例子)。

在您的特定情况下,程序员有责任确保如果存在引用,则引用的对象仍然存在,即存在引用的事实并不能保证该对象也存在,如果不存在(例如在你的例子中)代码是未定义的行为。奇怪的是,在 C++ 中有一个非常特殊的规则,在某些情况下,绑定(bind)引用的事实将“延长”应该立即丢弃的对象的生命...例如:

int foo() {
return 42;
}

int bar() {
const int& x = foo(); // Note... a const reference
return x;
}

这段代码是有效和正确的,但这是一个意外,因为有一条奇怪的规则说如果你将一个 const 引用绑定(bind)到一个临时的,临时的生命周期会延长到引用的生命周期。另请注意,这是一个非常微妙和精确的规则(例如,您必须了解 C++ 编译器的“临时”的法律术语),除非您 100% 地研究和理解该规则,否则您很可能会认为它即使不适用。

只是不要那样做。

关于c++ - 了解 C++ 如何返回引用并绑定(bind)到引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62508202/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com