C ++:变量还是引用?

时间:2018-08-19 03:19:31

标签: c++ variables reference initialization declaration

所以我在引用和指针上看到很多问题,但是我的困惑是变量和引用之间有什么区别。例如以下代码:

int main() {
    int ival = 1024;
    int &refVal = ival;
    cout << "refVal " << refVal << endl;
    cout << "&refVal " << &refVal << endl;
    cout << "&ival " << &ival << endl;
    return 0;
}

这些是输出:

refVal 1024
&refVal 0x7fff5f45b968
&ival 0x7fff5f45b968

因此,我们看到refValival具有完全相同的地址(?)和相同的值。他们只是同一件事吗?

我也很奇怪int ival = 1024语句会发生什么。我想像这样:

  • 在内存中创建一个类型为int的文字对象,其值为1024
  • 变量ival绑定到该对象。 ival是对该文字对象的引用吗?
  • 我猜想ival也将占用一些内存块,对吗?
  • refVal绑定到iVal,还是refVal绑定到ival也绑定到的文字对象(1024)?

谢谢!

13小时后更新:

再次感谢您的答复。如果可以的话,我想添加一些我认为会引起困惑的上下文:

  • 我从参考书《 C ++ Primer》 的2.3.1节中获得了示例代码。它没有解释引用的使用方式,我认为这使我感到困惑。尤其是。如果ivalrefval只是同一对象的两个名称,为什么我们完全需要概念“引用”?
  • 对我来说,在将变量传递给函数的上下文中,按引用比按值节省了一些内存。
  • 我仍然不确定为什么我们要独立引用变量。

5 个答案:

答案 0 :(得分:3)

int ival:这是内存堆栈部分中确实存在的已分配空间。

int &refVal:这只是'ival'的另一个名称,没有分配空间。

'&refVal'等于'&ival',它们都获得变量'ival'的内存地址。

答案 1 :(得分:2)

在内部,引用只是一个指针,主要区别在于您不需要使用特定于指针的语法,并且绝对不能为NULL

对于将参数传递给函数最有用,因为将对象作为参数传递给函数而不复制它的唯一其他方法是使用指针,然后您必须在各处使用指针语法。作为参考传递,可以使您的代码更加清晰和一致。

引用永远不会单独存在,它将始终引用现有变量。

答案 2 :(得分:1)

  

因此,我们看到refVal和ival具有完全相同的地址(?),并且   相同的值。他们是同一回事吗?

否,ival是一个变量:在这种情况下,它具有自己分配的堆栈内存。 refVal只是一个 bound 的名称,您可以将其传递给函数,而无需将ival的全部内存复制到函数中的局部变量(变量可能比int)大得多

int func1(int arg)
int func2(int& arg);

int var = 0;
int& varRef = var;

func1(var); // Entire memory of var is copied into the param named arg.
func2(varRef) // Just the address of 'var' is copied.

引用不能为 rebound ,并且对变量引用的任何赋值仅是对引用变量的赋值。

varRef = 1; // 'var' itself now has the value of '1'. 
  

在内存中创建一个int类型的文字对象,其值为1024

不完全是,这不是python。

  

一个变量,ival被绑定到该对象。 ival是指那个   文字对象?

不,没有绑定在这里执行。只是定期分配。 iVal是int类型的变量。

  

我想象ival也将占用一些内存块,对吗?

正确,它已为栈分配的块大小为int

  

是refVal绑定到iVal,还是refVal绑定到文字对象(1024)   那个节日也与之绑定?

同样,因为这里没有第三个“文字”对象,所以仅iVal表示int内存块,而refVal绑定到iVal

答案 3 :(得分:1)

通常,引用为is a variable。但是,引用不是它自己的对象。引用是引用现有对象的实体。

尽管在许多情况下(但不一定总是)编译器将使用相同的机制(即地址的传递)来实现指针,该机制也实现了引用,但在语言级别,指针和引用是完全相同的不同的东西。它们本质上都表示一个间接的。但是,指针是其自身的对象,具有自己的地址,需要显式地取消引用它,并且可以更改其值。引用不是对象本身(例如,它没有地址或大小),而是引用现有对象的实体。

声明

int ival = 1024;

是类型为int的对象的声明和定义,该对象已初始化为值1024。因此,是的,创建了一个int对象,名称为ival介绍。从那时起,ival是一个id-expression,表示那个特定的int对象。

声明

int &refVal = ival;

是引用的声明和定义,引用引用由表达式int指定的ival对象。从那时起,名称refVal是表示该对象的 id-expression 。因此,是的,名称refValival都指定相同的 int对象。

请注意,虽然ivalrefVal都是变量,但上面的两个声明语句仅创建一个对象,这是引入{的声明所定义的int对象{1}}。

通常,名称ival本身仅需要存储在编译期间编译器和链接器使用的内部数据结构(符号表)中。 ival只是您在代码中用来标识对象的名称。编译后的机器代码将仅访问标识符相应标识的任何对象(例如,通过其地址)。无需在程序的运行过程中显式表示名称(动态链接和调试信息除外)。您很可能在已编译(发行)二进制文件的任何位置都找不到字符串“ ival”。

答案 4 :(得分:0)

两者之间的区别是

变量: 变量为我们提供了程序可以操纵的命名存储。 C ++中的每个变量都有一个特定的类型,该类型确定变量的内存大小和布局。可以存储在该内存中的值的范围;以及可以应用于该变量的一组操作。

参考: 参考变量是别名,即已经存在的变量的另一个名称。使用变量初始化引用后,可以使用变量名或引用名来引用变量。

它基于https://www.tutorialspoint.com/cplusplus/

如果您仍然不了解它,请看下面的代码

 //Pointer
int *p0 ,*p1;
int firstv = 10, secondv = 20;
p0 = &firstv;
p1 = &secondv;
*p0 = 30; // first = 30
*p1 = *p0; // second = 30
std::cout << firstv << std::endl;
std::cout << secondv << std::endl;
p0 = p1; // p0 is pointing at secondv
*p0 = 50; // secondv is now = to 50
std::cout << firstv << std::endl;
std::cout << secondv << std::endl;

简而言之,就是上面提到的别名,它的作用是仅引用变量,一旦引用该变量,它将就像A =&B一样,并且基本上可以执行以下操作:更改变量A,变量B也将更改,因为它引用了该变量,正如您在有关p0的示例中所指的是firstv一样,并且当我们更改* p0 = 30时(由p0指向的值是=到30)在第6行中,firstv等于30

变量只是存储空间

摘要: 变量只是一个存储 引用是您用来引用变量的地址

在您的代码中,您将int&refVal = ival放在了正确的位置,因为&refVal引用的是您变量的地址,因此它的地址将相同。