const指针(不是指向const的指针)和引用之间的功能区别是什么?

时间:2015-10-05 06:08:53

标签: c++ pointers reference language-lawyer

我目前正在从C ++ Primer学习C ++,它解释了引用如何是另一个变量名的别名。它还解释了指针如何指向另一个变量。它指出指针和引用之间的区别在于指针可以重新分配,引用也可以。

在下面的代码示例中,我可以使用指针或引用来执行另一个操作吗?

double pi = 3.14;
double &piRef = pi;
double *const piPnt = π

//both of these examples are valid and do the same thing
piRef = 3.14159;
*piPnt = 3.14159;

//however, if I attempt to reassign what the pointer points to, it is illegal.
//this is the same as with a reference, as a reference can't be reassigned either
double tau = 6.28;
piPnt = τ

我知道每个的内部差异(例如指针是一个对象,一个引用是不是)。我感兴趣的是这些差异对程序员的影响如何超出略有不同的语法。因此,这不是this问题的重复,其中接受的答案仅涉及内部差异。

3 个答案:

答案 0 :(得分:6)

从功能的角度来看,指针和引用确实是一样的......它们引用一个对象而不是该对象的副本。

除了无法重新引用引用之外,唯一真正的区别是指针可以是NULL(即它可以指向任何内容),而假定引用始终引用对象。

从技术上讲,您实际上最终可以得到一个引用没有对象的引用(例如,将*p传递给期望p为空指针的引用的函数),但这是“未定义的行为”。

换句话说,指针比引用更“灵活”,这允许编译器忽略

  • 引用可以更改引用的对象
  • 引用可以没有对象

在某些情况下,这可以产生更快的代码(但是对于第二点,取消引用空指针是未定义的行为而不是运行时错误;因此编译器不会强制生成在这种情况下执行某些特殊操作的代码:从代码生成的角度来看,一个指针实际上指向没有对象的确是无关紧要的,因为它在程序员和编译器之间的契约中永远不会发生这种情况。)

支付重新绑定和NULL s的额外灵活性的“价格”是语法(有点无偿)更烦人。

如果指针无法重新分配(因为指针本身为const),那么除了更详细但显式的语法之外,没有任何实际差异。这是因为尽管是一个对象const - 声明指针即使使用别名也无法更改

从语法的角度来看,你可以获取const指针的地址,将地址转换为非const指针的地址并更改指向的值,这样的操作将是未定义的行为无论发生什么(例如忽略了分配),如果被告上法庭,编译器将是正确的: - )

答案 1 :(得分:5)

  

我可以用指针或参考做什么,而我可以用另一个做什么?

引用允许您编写某些构造函数和重载运算符:

class X
{
    // copy constructor
    X(const X& a);

    // move constructor
    X(X&& a);

    // copy assignment operator
    X& operator=(const X& a);

    // move assignment operator
    X& operator=(X&& a);
}

(实际上,运算符重载是将引用引入C ++的动机用例。)

经常被忽视的是,现代C ++区分X&(对左值的引用)和X&&(对右值的引用),但没有指针这样的东西到了右边。

答案 2 :(得分:1)

  

我可以用指针或参考来做什么我可以做的   其他

double *const piPnt = π

以上陈述

marks piPnt as a read only variable in memory layout

因此,piPnt = &xyz现在会抛出错误。

但是改变指针指向的地址的值仍然有效。

也就是说,*piPnt = 56没问题。

Const指针在需要引用相同内存(端口映射)的嵌入式系统中非常有用。它是一次性映射,常量指针在这里很有用。

现在关于参考文献:

double &piRef = pi;

您无法在C ++中重新初始化引用。您可以为其引用的对象指定不同的值。这是该参考文献永远的同一个对象。这就是你在你的例子中所做的。

piRef = 3.14159;
  

之后无法更改引用以引用其他对象   初始化。请注意,处理引用的初始化   与赋值完全不同。论证传递(5.2.2)和   函数值return(6.6.3)是初始化。

引用有用的地方:

  1. 指针不能指向临时工,标准明确禁止这样做。引用可以绑定到临时工。
  2. 指针可以为NULL,而假定引用始终引用对象。您仍然可以从返回引用的函数返回null,编译器不会抱怨它,但这是自杀。