如果null不是有效值,则使参数成为引用而不是指针

时间:2018-01-04 23:41:26

标签: c++ pointers reference

就我所知,它是一个很好的规则,如果参数可以合理地为null,那么像函数的参数类型的指针应该是指针,如果参数永远不应该为null,它应该是引用

基于那个"规则",我已经明确地期望做类似的事情 尝试拨打电话时,someMethodTakingAnIntReference(* aNullPointer)将失败,但令我惊讶的是,以下代码运行得很好,这使得"规则"不太可用。开发人员仍然可以从引用的参数类型中读取含义,但编译器没有帮助,运行时错误的位置也没有。

我是否误解了这条规则的要点,或者是这种未定义的行为,还是......?

int test(int& something1, int& something2)
{
    return something2;
}

int main()
{
    int* i1 = nullptr;
    int* i2 = new int{ 7 };

    //this compiles and runs fine returning 7.
    //I expected the *i1 to cause an error here where test is called
    return test(*i1, *i2); 
}

虽然上面的工作,但显然以下没有,但如果引用只是指针,情况也是如此;这意味着规则和编译器并没有真正起作用。

int test(int& something1, int& something2)
{
    return something1+something2;
}

int main()
{
    int* i1 = nullptr;
    int* i2 = new int{ 7 };


    //this compiles and runs returning 7.
    //I expected the *i1 to cause an error here where test is called
    return test(*i1, *i2); 
}

2 个答案:

答案 0 :(得分:1)

撰写test(*i1, *i2)会导致undefined behaviour;特别是部分*i1。这由[expr.unary.op] / 1:

在C ++标准中介绍
  

一元*运算符执行间接:应用它的表达式应该是指向对象类型的指针,或指向函数类型的指针,结果是引用对象或函数的左值其中的表达点。

仅在*X指向对象或函数的情况下定义X的行为。由于i1未指向对象或函数,因此标准不定义*i1的行为,因此它是未定义的行为。 (这有时被称为“遗漏未定义”,同样的做法处理不指定对象的左值的许多其他用法。)

如链接页面中所述,未定义的行为不需要任何类型的诊断消息。运行时行为实际上可以是任何东西。编译器可以,但不是必需的,生成编译警告或错误。通常,程序员必须遵守语言规则。编译器在某种程度上有所帮助,但它不能涵盖所有情况。

答案 1 :(得分:0)

你最好不要将引用视为一个方便的指针符号。

它们仍然是指针,当您使用(取消引用)空指针时,会发生运行时错误,而不是在将其传递给函数时。

(引用的另一个优点是,一旦初始化,它们就无法更改为引用其他内容。)