【问题标题】:Assigning a reference by dereferencing a NULL pointer通过取消引用 NULL 指针来分配引用
【发布时间】:2011-10-06 15:54:32
【问题描述】:
int&  fun()
{
    int * temp = NULL;
    return *temp;
}

在上述方法中,我正在尝试解除对 NULL 指针的引用。当我调用此函数时,它不会给出异常。我发现当返回类型是按引用时,如果它是按值,那么它不会给出异常。即使将 NULL 指针的取消引用分配给引用(如下行),它也不会给出。

int* temp = NULL:
int& temp1 = *temp;

这里我的问题是编译器在引用的情况下不做取消引用吗?

【问题讨论】:

  • 引用在内部作为指针处理,它们只是在您对它们使用的语法上有所不同。知道您的取消引用仅将指针值“分配”给引用,使其成为对 NULL 的引用。这不会触发任何内存访问。当您按值返回时,取消引用将导致内存访问为 0,这几乎总是会给您一个段错误。

标签: c++ pointers reference undefined-behavior null-pointer


【解决方案1】:

取消引用空指针是未定义的行为

未定义的行为意味着任何事情都可能发生,因此无法为此定义行为。

诚然,我将第 n 次添加此 C++ 标准引用,但似乎有必要。

关于未定义的行为,

C++ 标准第 1.3.24 节规定:

允许的未定义行为范围从完全忽略具有不可预测结果的情况,到在翻译或程序执行期间以环境特征的记录方式表现(无论是否发出诊断消息),到终止翻译或执行(发出诊断消息)。

注意:
此外,请注意:
使用返回的引用或指向函数内部局部变量的指针也是未定义行为。您应该使用 new 在 freestore(heap) 上分配指针,然后返回指向它的引用/指针。

编辑:
正如 @James McNellis 在 cmets 中适当指出的那样,
如果不使用返回的指针或引用,则行为定义明确

【讨论】:

  • 是的,同意上述 UB。但我的问题是,如果取消引用 NULL 指针或非 NULL 指针以将其分配给引用,那么编译器是否执行取消引用操作?像- Int * t = NULL; int&t1 = *t;
  • @G Mann:引用只是一个 alias 对它被初始化的原始类型。如何实现是编译器的实现细节,标准并没有定义它应该如何实现。
  • 当你引用一个空指针时,代码是无效的,编译器可以做任何事情。问为什么它做了什么是没有意义的。
  • @G Mann - 究竟会发生什么取决于引用的实现方式。标准也没有说,只是参考应该如何工作。
  • “在函数内部返回对局部变量的引用或指针也是一种未定义的行为。”这是不正确的:如果返回的指针或引用没有被使用,那么行为是定义良好的。
【解决方案2】:

当你取消引用一个空指针时,你不一定会得到一个异常;唯一可以保证的是行为是未定义的(这实际上意味着根本无法保证行为是什么)。

一旦对*temp 表达式求值,就无法推断程序的行为。

【讨论】:

  • 我正在添加与我在其他帖子中所做的相同的评论 - 是的,同意上述 UB。但我的问题是,如果取消引用 NULL 指针或非 NULL 指针以将其分配给引用,那么编译器是否执行取消引用操作?像- Int * t = NULL; int&t1 = *t;
  • 对于大多数编译器来说,在许多情况下,引用都是作为指针实现的。除此之外,还取决于编译器、设置等。
  • 纠正我我错了。如果它被实现为指针,那么编译器可能不会执行取消引用操作。
【解决方案3】:

不允许取消对空指针的引用,因此编译器可以在假设您不这样做的情况下生成代码。如果你仍然这样做,编译器可能会很好地告诉你,但它不是必须的。合同中规定你不能这样做。

在这种情况下,我打赌编译器很好地告诉你问题已经在编译时告诉你,如果你正确地设置警告级别。

【讨论】:

    【解决方案4】:

    不要 * 一个空指针,它是 UB。 (未定义的行为,你永远不能假设它会做任何事情,除了点燃你的狗并强迫你吃蘑菇,这会导致神话般的轶事)

    Algol/C家族中空指针的一些历史和资料:http://en.wikipedia.org/wiki/Pointer_(computing)#Null_pointer

    未定义行为的示例和含义:http://en.wikipedia.org/wiki/Undefined_behavior#Examples_in_C

    【讨论】:

      【解决方案5】:

      我不确定我是否理解您要执行的操作。未定义 ** NULL** 指针的取消引用。

      如果你想表明你的方法并不总是返回值,你可以将它声明为:

      bool fun(int &val);

      或stl方式(类似于std::map插入):

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

      或提升方式:

      boost::optional<int> fun();
      

      【讨论】:

        猜你喜欢
        • 2021-09-05
        • 1970-01-01
        • 1970-01-01
        • 2012-07-06
        • 1970-01-01
        • 1970-01-01
        • 2020-07-14
        • 2017-04-17
        相关资源
        最近更新 更多