【问题标题】:Whats the difference between reference to an array and array as a parameters in functions?引用数组和数组作为函数中的参数有什么区别?
【发布时间】:2022-01-20 14:45:14
【问题描述】:

引用数组的函数有什么区别:

// 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*。

那么毕竟,这些功能之间有什么实际区别吗?

【问题讨论】:

  • 尝试将数组作为参数传递给您的两个函数,并看到第一个失败。 (第二个实际上是一个指针,而不是一个数组。)
  • 我编辑了这个问题。函数采用精确大小的数组。
  • 第二个还是带指针;当没有参考时,忽略大小。
  • 第二个实际上并不采用精确大小的数组。它需要一个指针。试试看!
  • 这并没有解决问题,但是包含两个连续下划线 (f__) 的名称和以下划线后跟大写字母的名称保留供实现使用。不要在你的代码中使用它们。

标签: c++ c++11 pass-by-reference implicit-conversion


【解决方案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.

【讨论】:

  • 谢谢,但第一个示例无法编译。您需要像这样指定 size_t 参数: template void f(int (&a)[N]) {};
  • @hgrev 我不是说模板函数。我的意思是非模板函数。 N 是某个常量表达式或不存在它。
  • 是的,我的意思也是非模板函数,但是在你指定 N 之前它不会编译
  • @hgrev 看来您使用的是旧编译器或包含错误的编译器。请参阅我更新的帖子。您可以在 www.godbolt.org 上试用该程序
  • 那么请您解释一下“以及在函数内您将知道传递数组中元素的数量”。如果我不指定 N ?
【解决方案2】:

由于您不能按值传递数组(C++ 继承的 C 限制),任何将参数声明为数组都会“衰减”为指针(失去其大小)。所以声明

void f__(char t[5])

等同于

void f__(char *t)

其他一切都由此而来——在f__ 的主体中,t 具有指针类型,而不是数组类型。因此任何auto 的推断都将基于该指针类型。

【讨论】:

    猜你喜欢
    • 2015-02-07
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多