引用数组和数组作为函数参数有什么区别?
Whats the difference between reference to an array and array as a parameters in functions?
引用数组的函数有什么区别:
// reference to array
void f_(char (&t)[5]) {
auto t2 = t;
}
简单数组:
// just array
void f__(char t[5]) {
auto t2 = t;
}
作为参数?
调用代码为:
char cArray[] = "TEST";
f_(cArray);
f__(cArray);
char (&rcArr)[5] = cArray;
f_(rcArr);
f__(rcArr);
在这两种情况下,t2 都是 char*,但在第一个函数中,我的 VS2019 显示 t 内部函数的类型为 char(&t)[] 和 t 内部第二个函数的类型为 char*.
那么说到底,这些函数之间有什么实际区别吗?
您可以指定一个完整的数组类型参数,例如
void f( int ( &a )[N] );
并且在函数中您将知道传递的数组中的元素数。
当函数被声明为
void f( int a[] );
然后编译器将函数声明调整为
void f( int *a );
并且您无法确定传递的数组中的元素数量。所以你需要指定第二个参数,比如
void f( int *a, size_t n );
还可以重载具有引用数组参数类型的函数。例如这两个声明
void f( int ( &a )[] );
和
void f( int ( &a )[2] );
声明两个不同的函数。
并且可以使用花括号列表调用具有引用数组参数类型的函数(前提是相应的参数具有限定符 const),例如
f( { 1, 2, 3 } );
这是一个演示程序
#include <iostream>
void f( const int ( &a )[] )
{
std::cout << "void f( const int ( & )[] ) called.\n";
}
void f( const int ( &a )[2] )
{
std::cout << "void f( const int ( & )[2] ) called.\n";
}
void f( const int a[] )
{
std::cout << "void f( const int [] ) called.\n";
}
int main()
{
f( { 1, 2, 3 } );
}
程序输出为
void f( const int ( & )[] ) called.
由于不能按值传递数组(C++ 继承的 C 限制),任何将参数声明为数组的参数都会 'decay' 变成指针(失去其大小)。所以声明
void f__(char t[5])
等同于
void f__(char *t)
其他所有内容都由此而来——在 f__
的主体内,t
具有指针类型,而不是数组类型。因此,从中推断出的任何 auto
都将基于该指针类型。
引用数组的函数有什么区别:
// reference to array
void f_(char (&t)[5]) {
auto t2 = t;
}
简单数组:
// just array
void f__(char t[5]) {
auto t2 = t;
}
作为参数?
调用代码为:
char cArray[] = "TEST";
f_(cArray);
f__(cArray);
char (&rcArr)[5] = cArray;
f_(rcArr);
f__(rcArr);
在这两种情况下,t2 都是 char*,但在第一个函数中,我的 VS2019 显示 t 内部函数的类型为 char(&t)[] 和 t 内部第二个函数的类型为 char*.
那么说到底,这些函数之间有什么实际区别吗?
您可以指定一个完整的数组类型参数,例如
void f( int ( &a )[N] );
并且在函数中您将知道传递的数组中的元素数。
当函数被声明为
void f( int a[] );
然后编译器将函数声明调整为
void f( int *a );
并且您无法确定传递的数组中的元素数量。所以你需要指定第二个参数,比如
void f( int *a, size_t n );
还可以重载具有引用数组参数类型的函数。例如这两个声明
void f( int ( &a )[] );
和
void f( int ( &a )[2] );
声明两个不同的函数。
并且可以使用花括号列表调用具有引用数组参数类型的函数(前提是相应的参数具有限定符 const),例如
f( { 1, 2, 3 } );
这是一个演示程序
#include <iostream>
void f( const int ( &a )[] )
{
std::cout << "void f( const int ( & )[] ) called.\n";
}
void f( const int ( &a )[2] )
{
std::cout << "void f( const int ( & )[2] ) called.\n";
}
void f( const int a[] )
{
std::cout << "void f( const int [] ) called.\n";
}
int main()
{
f( { 1, 2, 3 } );
}
程序输出为
void f( const int ( & )[] ) called.
由于不能按值传递数组(C++ 继承的 C 限制),任何将参数声明为数组的参数都会 'decay' 变成指针(失去其大小)。所以声明
void f__(char t[5])
等同于
void f__(char *t)
其他所有内容都由此而来——在 f__
的主体内,t
具有指针类型,而不是数组类型。因此,从中推断出的任何 auto
都将基于该指针类型。