通过取消引用一个空指针来分配一个引用

13
int&  fun()
{
    int * temp = NULL;
    return *temp;
}
在上述方法中,我试图对空指针进行解引用。当我调用此函数时,它不会抛出异常。我发现当返回类型为引用时,如果返回类型为值,则不会抛出异常。即使将空指针的解引用分配给引用(如下行),它也不会抛出异常。
int* temp = NULL:
int& temp1 = *temp;

我的问题是,对于引用,编译器是否不需要进行解引用操作?


4
参考文献在内部被处理为指针,只是在使用语法上与其不同。了解到您的取消引用只是将指针值“赋值”给参考,使其成为NULL的参考。这并不会触发任何内存访问。当您按值返回时,取消引用将导致在0处进行内存访问,几乎总是会导致段错误。 - Nobody moving away from SE
5个回答

17
解引用空指针是未定义行为。
未定义行为意味着任何事情都有可能发生,因此无法定义其行为。
诚然,我将再次添加C ++标准引用,但似乎需要这样做。
关于未定义行为,
C++标准第1.3.24节规定:
允许的未定义行为范围从完全忽略具有不可预测结果的情况,到在环境特征下(带或不带诊断消息)在翻译或程序执行期间表现出来,直到终止翻译或执行(带有诊断消息)。
注意:
此外,提醒您注意:
在函数内部使用对局部变量返回的引用或指针也是未定义行为。您应该在堆上使用new分配指针,然后返回对它的引用/指针。
编辑:
正如@James McNellis在评论中适当地指出的那样,
如果未使用返回的指针或引用,则行为是良好定义的。

1
@G Mann:引用只是对其初始化的原始类型的“别名”。它的实现方式是编译器的实现细节,标准并没有定义它应该如何实现。 - Alok Save
2
当您解引用空指针时,代码无效,编译器可以执行任何操作。询问为什么它执行任何操作是没有意义的。 - Bo Persson
1
@G Mann - 具体发生什么取决于引用的实现方式。标准也没有说明这一点,只是说明了引用应该如何工作。 - Bo Persson
4
如果在函数内返回一个局部变量的引用或指针,这也是未定义的行为。这是不正确的:如果没有使用返回的指针或引用,则行为是被定义的。 - James McNellis
@James McNellis:感谢您仔细阅读!像往常一样,您的评论非常出色,发现得很好。我修改了答案以反映这一点。 - Alok Save
显示剩余4条评论

7
当您取消引用空指针时,并不一定会得到异常,所有保证的只是行为未定义(这实际上意味着根本没有任何关于行为的保证)。
一旦评估了“*temp”表达式,就无法推断程序的行为。

我在这里添加与其他帖子相同的评论 - 是的,我同意上面提到的UB。 但我的问题是,如果将NULL指针或非NULL指针的解引用赋给引用,编译器是否执行解引用操作?例如- Int * t = NULL; Int&t1 = * t; - G Mann
对于大多数编译器,在许多情况下,引用被实现为指针。除此之外,这取决于编译器、设置等因素。 - James McNellis
如果我的理解有误,请纠正我。在指针实现的情况下,编译器可能不会执行解引用操作。 - G Mann

4
你不允许解引用一个空指针,因此编译器会生成假设你不这样做的代码。如果你仍然这样做,编译器可能会友好地告诉你,但它没有必要。这是你的合同的一部分,说你不能这样做。
在这种情况下,如果你将警告级别设置正确,我敢打赌编译器会友好地在编译时告诉你问题。

1

0

我不确定我理解你想做什么。对 ** NULL ** 指针的取消引用未定义。

如果您想表明您的方法并非总是返回值,您可以将其声明为:

bool fun(int &val);

或者使用STL方式(类似于std :: map insert):

std::pair<int, bool> fun();

或者使用boost库的方式:

boost::optional<int> fun();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接