Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 声明对int数组的引用时,为什么必须是对const指针的引用?_C++_Arrays_Pointers_Reference_Constants - Fatal编程技术网

C++ 声明对int数组的引用时,为什么必须是对const指针的引用?

C++ 声明对int数组的引用时,为什么必须是对const指针的引用?,c++,arrays,pointers,reference,constants,C++,Arrays,Pointers,Reference,Constants,注意:我使用的是g++编译器(我听说它非常好,应该非常接近标准) 假设您已经声明了一个整数数组: int a[3] = { 4, 5, 6 }; 现在让我们假设您真的想要声明对该数组的引用(不管为什么,除了Bjarne说该语言支持它之外) 案例1——如果您尝试: int*& ra = a; int*const&rca = a; //wish I knew where the spaces should go (but my other post asking about

注意:我使用的是g++编译器(我听说它非常好,应该非常接近标准)


假设您已经声明了一个整数数组:

int a[3] = { 4, 5, 6 };
现在让我们假设您真的想要声明对该数组的引用(不管为什么,除了Bjarne说该语言支持它之外)

案例1——如果您尝试:

int*& ra = a;
int*const&rca = a;  //wish I knew where the spaces should go (but my other post asking about this sort of protocol got a negative rank while many of the answers got ranked highly -- aha! there are stupid questions!) 
然后编译器犹豫了一下,说:

"invalid initialization of non-const reference of type `int*&' from a temporary of type `int*'"  
首先,为什么“a”是一个临时变量(即,它在内存中没有位置?)

不管怎样,好吧,每当我看到一个非常量错误,我都会尝试加入一个常量

案例2——如果您尝试:

int*& ra = a;
int*const&rca = a;  //wish I knew where the spaces should go (but my other post asking about this sort of protocol got a negative rank while many of the answers got ranked highly -- aha! there are stupid questions!) 
然后一切都很酷,它编译了,你得到了一个数组的引用

案例3——下面是另一个需要编译的东西:

int* justSomeIntPointer = a;  //LINE 1
int*& rpa = justSomeIntPointer;  //LINE 2
这还提供了对原始数组的引用

所以我的问题是:静态声明数组的名称在哪一点 成为常数指针?我似乎记得int数组的名称也是指向int的指针,但我不记得它曾经是指向int的const-pointer

案例1似乎失败了,因为声明的引用(ra)不是指向常量指针,这可能意味着“a”已经是指向int的常量指针

看起来案例2是可行的,因为声明的引用(rca)已经是常量指针指向int

案例3也有效,这很简单,但为什么呢?假定指向int的指针(即数组名“a”)在什么时候变成常量指针?它是在您将其分配给int*(第1行)时发生的,还是在您将该int*分配给int*&(第2行)时发生的


希望这是有意义的。谢谢。

a是一个临时变量,因为您使用malloc或new在堆栈上而不是在堆上声明了它。

静态声明数组的名称在什么时候变成常量指针?我似乎记得int数组的名称也是指向int的指针,但我不记得它曾经是指向int的const-pointer

因为您在cpp文件中写入了这些值,所以它是常量

您只需使用:

const int *pToArray = a;

int*
是指针类型,而不是数组类型。这就是为什么它不会绑定到
a
,它的类型是
int[3]

int* const& ra = a;
有效,因为它相当于

int* const& ra = (int*)a;
也就是说,概念上在赋值的右侧创建一个临时指针,然后将该临时指针绑定到
ra
。因此,最终,这并不比:

int* ra = a;
其中,
ra
实际上是指向数组第一个元素的指针,而不是数组的引用

声明对数组的引用非常简单:

typedef int array_type[3];
array_type& ra = a;
这不是一个简单的方法:

typedef int array_type[3];
array_type& ra = a;
int (&ra)[3] = a;
auto& ra = a;
C++11简易方法:

typedef int array_type[3];
array_type& ra = a;
int (&ra)[3] = a;
auto& ra = a;

静态声明数组的名称在什么时候变成常量指针?我似乎记得int数组的名称也是指向int的指针,但我不记得它曾经是指向int的const-pointer

这是一个正确的问题!如果您了解数组到指针的衰减是何时发生的,那么您就安全了。简单地说,有两件事需要考虑:

  • 当尝试任何类型的“复制”时都会发生衰减(因为C不允许直接复制数组)
  • 衰变是一种转换,可以在允许转换的任何时候发生:当类型不匹配时
第一类通常发生在模板中。因此,给定
模板通过值(T)
,则
passby\u值(a)
实际上将传递一个
int*
,因为不能复制
int[3]
类型的数组

至于第二个,你已经看到了它的作用:在第二个例子中,当
int*const&
不能绑定到
int[3]
,但可以绑定到一个临时的
int*
,转换就发生了。

非常大的错误(也是一个非常好的面试问题)大多数人认为数组的名称等同于指针。事实并非如此。这个错误导致了C程序中的许多错误,尤其是链接错误,并且它们很难调试。区别在于:数组的名称是指针,是结构的第一个元素,数组。但是,数组名称的类型不是pointertype,而是arraytype。另一方面,指针只是指向一个事物的指针,没有其他信息。指针的类型是指针类型。arraytype还有一些其他属性,比如它知道它是否在堆栈上;因此,“临时”。本例中的临时错误来自一个阻止将临时变量分配给引用的检查。const关键字将关闭该检查。另一方面,指针类型没有“临时”的概念。现在假设您想要欺骗编译器,并为堆栈中的某个对象分配引用。在这种情况下,需要将其设置为指针。怎么做

int*&ra=&a[0]


在上述情况下,首先获取值,然后使用&(address of operator)生成pointerType。现在,pointertype没有关于其是否在堆栈上(临时变量)的信息。但是,这将引用指向数组第一个元素的指针。(因此只是指针类型,而不是arraytype)

如果确实需要对数组的引用,则应使用以下命令:

int a[3] = { 4, 5, 6 };
int (&ra)[3] = a;

您试图用
int*&
创建的是指向int的指针的引用。这不是同一类型。当您使用无法更改的值(数组地址)初始化引用时,您必须声明指针常量(而不是整数)。

您有一个整数数组:

int a[3] = { 4, 5, 6 };
现在,这一行:

int*& ra = a;
创建对指针的引用。由于创建了临时指针(从数组a转换而来),编译器会抱怨,因为标准禁止将临时指针分配给