提问人:hgrev 提问时间:12/18/2021 最后编辑:Vlad from Moscowhgrev 更新时间:12/18/2021 访问量:316
在函数中引用数组和数组作为参数有什么区别?
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*。
那么,这些功能之间到底有什么实际区别吗?
答:
2赞
Vlad from Moscow
12/18/2021
#1
例如,您可以指定一个完整的数组类型参数
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.
评论
0赞
hgrev
12/18/2021
谢谢,但第一个示例无法编译。您需要指定size_t参数如下: template<size_t N> void f(int (&a)[N]) {};
0赞
Vlad from Moscow
12/18/2021
@hgrev 我不是说模板函数。我的意思是非临时函数。N 是某种常量表达式或不存在常量表达式。
0赞
hgrev
12/18/2021
是的,我的意思是非模板函数,但在您指定 N 之前它不会编译
0赞
Vlad from Moscow
12/18/2021
@hgrev 您似乎正在使用旧的编译器或包含错误的编译器。请参阅我更新的帖子。您可以在 www.godbolt.org 试用该程序
1赞
Vlad from Moscow
12/18/2021
@hgrev 如果参数中的元素数指定为例如 void f( int ( &a )[10] );然后你就会知道这个数字了:) 您可以将运算符 sizeof 应用于参数,您将获得数组的确切大小。当参数没有引用类型时,即使您指定 void f( int a[10] );编译器会调整函数声明,如 void f( int *a );也就是说,您将处理一个指针。
0赞
Chris Dodd
12/18/2021
#2
由于不能按值传递数组(C++ 继承的 C 限制),因此任何将参数声明为数组都将“衰减”为指针(失去其大小)。所以宣言
void f__(char t[5])
等同于
void f__(char *t)
其他所有内容都由此而来 -- 在 的主体中,有一个指针类型,而不是数组类型。因此,从它进行的任何推断都将基于该指针类型。f__
t
auto
评论
f__