要求基本的C ++语法细节;使用&内部初始化与外部初始化

时间:2015-08-19 19:27:32

标签: c++

所以,我知道编写C ++代码的人可以这样做:

    double *doublePtr;             // Declares a pointer.
    double doubleVal = 8.234;      // Declares and initializes a double.
    doublePtr = &doubleVal;        // Makes pointer point to doubleVal.

此外,编写C ++代码的人可以这样做:

    double doubleVal = 8.234;      // Declares and initializes a double.
    double &doubleRef = doubleVal; // Declares/Initializes a reference
                                   // To the address of doubleVal (???).
                                   // But why isn't doubleVal instead
                                   // &doubleVal if it's an address that
                                   // &doubleRef is being initialized with.

那么,为什么不适合(由于编译器错误)这样做:

    double dVala = 1.234, dValb = 3.456;
    &dVala = &dValb;

更具体地说,我试图提出这样一个问题,“我对此感到困惑的是什么,通过一个简单的解释,将使这一点的具体细节更加明确”。是否引用了C ++常量的内置数据类型,以便它们只能用值初始化,但在初始化后不能随时更改?

当然,我们可以将变量地址的值输出到某种数据类型,如下所示:

    double dVala = 23.456;
    cout << &dVala;

我希望我的问题很明确。感谢。

2 个答案:

答案 0 :(得分:7)

符号&具有多种含义,具体取决于上下文:你不能只从一个地方拿它,把它放在另一个地方,并期望完全相同的事情发生。

  1. 当用作两个表达式之间的运算符时,它是按位AND。
  2. 装饰类型名称时,表示“引用”。
  3. 在表达式前面,表示“address-of”。
    • 你的第一个工作示例声明了一个指针并且没有初始化它,但后来为它指定了一个对象的地址。
    • 您的第二个工作示例声明并初始化对象的引用。
    • 您的破解示例尝试将一件事的地址分配给另一件事的地址。它没有任何意义。

    除此之外:

      

    是否引用C ++常量的内置数据类型,以便它们只能用值初始化,但在初始化后不能随时更改?

    是。 所有引用本身都是不可变的,并且在初始化后无法重新定位。

    正如我们上面所探讨的,写&someReference实际上并没有“访问”引用本身;实际上,没有这样做的语法。

      

    但是为什么不是doubleVal而不是doubleVal,如果它是&amp; doubleRef正在初始化的地址。

    因为那时引用在很大程度上与指针无法区分,因此毫无意义(lol)。

    请勿将double& doubleRef视为&doubleRef。不是。这是一个名为double&的{​​{1}}。

    引用“为你做解除引用”。它们直接绑定到对象而无需您自己获取地址。

    这是该语言的礼物。

答案 1 :(得分:0)

我认为你会发现学习一些基本装配非常有启发性。这样,您就可以准确地看到您的C ++代码是如何用CPU的本地语言表达的。为了帮助您了解代码发生了什么,让我们将其分解为汇编。这是我从MSVC2013获得的所有优化关闭。每个块代表原始代码的一行:

double doubleVal = 8.234;
movsd   xmm0,mmword ptr [test!_real (00000001`3f2948b8)]
movsd   mmword ptr [rsp],xmm0

doublePtr = &doubleVal;
lea     rax,[rsp]
mov     qword ptr [rsp+8],rax

double &doubleRef = doubleVal;
lea     rax,[rsp]
mov     qword ptr [rsp+10h],rax

这里没有显示的是编译器以这样的方式设置代码,即在内存中有三个变量的空间。第一个是变量doublVal,它位于存储在CPU寄存器rsp中的存储器地址中。同样,doublePtrdoubleRef存储在rsp+8rsp+10h(这些是十六进制值,顺便说一句)。这个间距反映了变量长度为8个字节的事实。

现在,前两个指令(movsd)将一个常量值(8.234)移动到浮点寄存器中,然后将其移动到rsp中存储的地址({{1}的位置) })。现在doubleVal被初始化为您指定的常量。

下一个块采用doubleVal的地址(存储在doubleVal中)并将其复制到CPU寄存器rsp,然后将rax中的值复制到该地址raxrsp+8的位置)。现在doublePtr已初始化为doublePtr

的地址

第三个块与第二个块相同,但doubleVal的地址被复制到变量doubleVal(其地址存储在doubleRef)中除外。这表明编译器使用指针实现了您的引用变量,这是相当典型的。