为什么我们不能将 int array[] 传递给 hoo(int* &p)?
Why can't we pass int array[] to hoo(int* &p)?
在我的理解中,int array[]={1,2,3,4,5}
中的array
只是指向array
的第一个元素的指针。这意味着 array
可以分配给 int*
.
类型的指针 ptr
hoo
中的参数 int* &p
将通过引用传递参数。这意味着我们可以更改传递的参数以指向 hoo
中的另一个值。
void hoo(int* &p, int n)
{
for (int i = 0; i < n; i++)
cout << p[i] << endl;
}
int main()
{
int array[] = { 1,2,3,4,5 };
// I can do this
int* ptr = array;
hoo(ptr, 5);
// but not this.
//hoo(array, 5);
}
问题
为什么我们不能在没有 ptr
的情况下将 int array
传递给 hoo
?
In my understanding array in int array[]={1,2,3,4,5} is just a pointer to the first element of array.
这是不正确的。数组是数组,指针是指针。它们是具有不同属性的不同类型。他们经常感到困惑,因为数组具有 属性,它会急切地衰减到指向其第一个元素的指针。
hoo(array, 5);
尝试将 array
转换为 int*
,但该转换的结果是右值,不能绑定到非 const
引用.例如,如果您将 hoo
更改为采用 const
引用,它将编译正常:
void hoo(int* const &p, int n) { }
int main()
{
int array[] = { 1,2,3,4,5 };
hoo(array, 5);
}
在那种情况下,您无法更改 p
指向的内容,从而使引用毫无意义。
当一个函数接受一个 int* &
参数时,也就是说,一个(非移动)引用指向一个 int
的指针 - 然后需要一个真正的指针该引用所指的变量。它不能是临时指针值。因此你不能这样做:
int x;
hoo(&x, 123);
因为没有可引用的指针变量 - 只是临时变量。这与您的 int[5]
本质上是一样的。实际上任何地方都没有 int*
变量——只有 5 个 int
。当您将 array
传递给 hoo()
时,C++ 使用该标识符所做的是一个 array-to-pointer decay:它实际上传递了 &(array[0])
。所以就像前面的例子一样,那不会编译。
其他答案已经说明问题了。我想建议更改编码实践。
使用void hoo(int* &p, int n)
作为函数声明是非常古老的风格。使用模板,您可以让编译器推断大小并获得对数组的引用,从而避免使用指针。
template <size_t N>
void hoo( int (&p)[N]) // The argument is a reference to an array of N elements.
{
for (int i = 0; i < N; i++)
cout << p[i] << endl;
}
函数的调用变得自然。
int array[] = { 1,2,3,4,5 };
hoo(array);
如果您的函数也需要能够支持动态分配的数组,您可以按如下方式重载该函数。
void hoo(int* p, size_t N)
{
for (int i = 0; i < N; i++)
cout << p[i] << endl;
}
template <size_t N>
void hoo( int (&p)[N]) // The argument is a reference to an array of N elements.
{
hoo(p, N);
}
在我的理解中,int array[]={1,2,3,4,5}
中的array
只是指向array
的第一个元素的指针。这意味着 array
可以分配给 int*
.
ptr
hoo
中的参数 int* &p
将通过引用传递参数。这意味着我们可以更改传递的参数以指向 hoo
中的另一个值。
void hoo(int* &p, int n)
{
for (int i = 0; i < n; i++)
cout << p[i] << endl;
}
int main()
{
int array[] = { 1,2,3,4,5 };
// I can do this
int* ptr = array;
hoo(ptr, 5);
// but not this.
//hoo(array, 5);
}
问题
为什么我们不能在没有 ptr
的情况下将 int array
传递给 hoo
?
In my understanding array in int array[]={1,2,3,4,5} is just a pointer to the first element of array.
这是不正确的。数组是数组,指针是指针。它们是具有不同属性的不同类型。他们经常感到困惑,因为数组具有 属性,它会急切地衰减到指向其第一个元素的指针。
hoo(array, 5);
尝试将 array
转换为 int*
,但该转换的结果是右值,不能绑定到非 const
引用.例如,如果您将 hoo
更改为采用 const
引用,它将编译正常:
void hoo(int* const &p, int n) { }
int main()
{
int array[] = { 1,2,3,4,5 };
hoo(array, 5);
}
在那种情况下,您无法更改 p
指向的内容,从而使引用毫无意义。
当一个函数接受一个 int* &
参数时,也就是说,一个(非移动)引用指向一个 int
的指针 - 然后需要一个真正的指针该引用所指的变量。它不能是临时指针值。因此你不能这样做:
int x;
hoo(&x, 123);
因为没有可引用的指针变量 - 只是临时变量。这与您的 int[5]
本质上是一样的。实际上任何地方都没有 int*
变量——只有 5 个 int
。当您将 array
传递给 hoo()
时,C++ 使用该标识符所做的是一个 array-to-pointer decay:它实际上传递了 &(array[0])
。所以就像前面的例子一样,那不会编译。
其他答案已经说明问题了。我想建议更改编码实践。
使用void hoo(int* &p, int n)
作为函数声明是非常古老的风格。使用模板,您可以让编译器推断大小并获得对数组的引用,从而避免使用指针。
template <size_t N>
void hoo( int (&p)[N]) // The argument is a reference to an array of N elements.
{
for (int i = 0; i < N; i++)
cout << p[i] << endl;
}
函数的调用变得自然。
int array[] = { 1,2,3,4,5 };
hoo(array);
如果您的函数也需要能够支持动态分配的数组,您可以按如下方式重载该函数。
void hoo(int* p, size_t N)
{
for (int i = 0; i < N; i++)
cout << p[i] << endl;
}
template <size_t N>
void hoo( int (&p)[N]) // The argument is a reference to an array of N elements.
{
hoo(p, N);
}