在 C++ 中返回数组引用的语法
Syntax for returning an array reference in C++
我一直在复习 C++ 中的数组概念,当我遇到这个问题时:Return an array in c++
有人用这个声明回答:
int (&f(int (&arr)[3]))[3]
我似乎无法理解的是右括号后的 [3]。我从未见过像这样的函数声明。我了解其余的语法,但我不是特别了解 [3] 是如何工作的,因为它在函数名称之后。如果我忽略了一些简单的事情,我会提前道歉。我还尝试查看函数声明的规范,但我没有看到任何与下标语法相关的内容 link 。那么,这怎么可能呢?
该函数返回一个 reference 到一个大小为 3
的 int
的数组,函数后面的 [3]
部分实际上是要作为 reference.
返回的数组的大小
这个晦涩的语法来自数组声明的奇怪语法,你这样做:
int arr[3]; //real but weird
如果有这样的话,语言会简单得多:
int[3] arr; //hypothetical but better and simpler
因为大小3
是arr
类型的部分,所以如果所有的部分都出现在左边更有意义变量名,和你写的一样:
unsigned int a;
你不写:
unsigned a int; //analogous to : int a [3];
因此,尽管该语言对 unsigned int
做了正确的事情,但对 int[3]
做了一件非常奇怪的事情。
现在回到函数声明,函数声明为:
int[3]& f(int[3]& arr); //hypothetical
仅当它的所有部分都在变量名的左侧时。但由于它不这样做(即语言 要求 你在变量名后的最右边写上大小),你最终得到这个奇怪的签名:
int (&f(int (&arr)[3])[3]; //real
请注意,参数甚至变得很奇怪。
但您可以使用 typedef 将其简化为:
typedef int array_type[3];
array_type& f(array_type& arr);
看起来好多了。现在只有 typedef 看起来很奇怪。
使用 C++11,您可以编写更好的 typedef:
using array_type = int[3];
array_type& f(array_type& arr);
与此非常接近(如果您将 array_type
可视化为 int[3]
):
int[3]& f(int[3]& arr); //hypothetical
希望对您有所帮助。
int (&f (int (&arr)[3]) )[3]
{
return arr;
}
让我们从里面走吧。 (int (&arr)[3])
部分表示该函数将对 3 个元素的 int 数组的引用作为参数。这与正在 return 编辑的 arr
相同。
现在,语法的其余部分表示该函数应该 return 对 3 个整数数组的引用。 f
是函数的名称。 int &f()
意味着您 return 对 int
的引用,但您需要 return 固定大小的数组,因此您应该添加 [3]
使用 &f(...)
周围的括号是因为在 C++ 中,您将数组的大小写在变量名之后,而不是类型名之后,正如 Nawaz 在他的回答中所解释的那样。如果省略这些括号,编译器会将 f
解释为引用数组,如 int & f[3]
.
好吧,阅读这篇 article 关于 C 历史的文章,作者 Dennis M. Ritchie。
看起来像我们从 B、C 到 C++ 得到的这种语法...
我相信,这种声明一些 "basic type" 的多个变量的方式是这种奇怪语法的根源:
int a, *b, c[3];
所以 a
只是 int
,b
是指向 int
的指针,而 c
是 int
的数组...
如果这些 *
和 [3]
是类型定义的一部分而不是变量定义 - 那么我们需要 3 行来编写:
int a;
int* b;
int[3] c;
SO C page 上有两个很好的资源可用于学习如何解析此类结构:
- The Clockwise/Spiral Rule for parsing C declarations.
- cdecl: C gibberish ↔ English, a site that translate C expressions to readable English.
cdecl 有点失败 - 因为引用不是 C 的一部分 - 所以让我们尝试 The Clockwise/Spiral Rule for parsing C declarations.
int (&f(int (&arr)[3]))[3]
arr
-> arr
&arr
-> arr 是引用
(&arr)
-> arr 是参考 - 周围 ()
并没有真正改变什么
(&arr)[3]
-> arr 是对大小为 3 的数组的引用
int (&arr)[3]
-> arr 是对 int 类型的大小为 3 的数组的引用
下一个:
f
-> f
f(int (&arr)[3])
-> f 是接受 arr 的函数,即 ...
&f(int (&arr)[3])
-> f 是接受 arr 的函数,它是 ...,并返回引用
(&f(int (&arr)[3]))[3]
-> f 是接受 arr 的函数,它是...,并返回对大小为 3 的数组的引用
int (&f(int (&arr)[3]))[3]
-> f 是接受 arr 的函数,arr 是对 int 类型大小为 3 的数组的引用,并返回对大小为 3 的 int 类型数组的引用
当然 - 至少对我而言,此代码应替换为更易于阅读的版本:
using int3 = int[3];
int3& f(int3& arr);
我一直在复习 C++ 中的数组概念,当我遇到这个问题时:Return an array in c++
有人用这个声明回答:
int (&f(int (&arr)[3]))[3]
我似乎无法理解的是右括号后的 [3]。我从未见过像这样的函数声明。我了解其余的语法,但我不是特别了解 [3] 是如何工作的,因为它在函数名称之后。如果我忽略了一些简单的事情,我会提前道歉。我还尝试查看函数声明的规范,但我没有看到任何与下标语法相关的内容 link 。那么,这怎么可能呢?
该函数返回一个 reference 到一个大小为 3
的 int
的数组,函数后面的 [3]
部分实际上是要作为 reference.
这个晦涩的语法来自数组声明的奇怪语法,你这样做:
int arr[3]; //real but weird
如果有这样的话,语言会简单得多:
int[3] arr; //hypothetical but better and simpler
因为大小3
是arr
类型的部分,所以如果所有的部分都出现在左边更有意义变量名,和你写的一样:
unsigned int a;
你不写:
unsigned a int; //analogous to : int a [3];
因此,尽管该语言对 unsigned int
做了正确的事情,但对 int[3]
做了一件非常奇怪的事情。
现在回到函数声明,函数声明为:
int[3]& f(int[3]& arr); //hypothetical
仅当它的所有部分都在变量名的左侧时。但由于它不这样做(即语言 要求 你在变量名后的最右边写上大小),你最终得到这个奇怪的签名:
int (&f(int (&arr)[3])[3]; //real
请注意,参数甚至变得很奇怪。
但您可以使用 typedef 将其简化为:
typedef int array_type[3];
array_type& f(array_type& arr);
看起来好多了。现在只有 typedef 看起来很奇怪。
使用 C++11,您可以编写更好的 typedef:
using array_type = int[3];
array_type& f(array_type& arr);
与此非常接近(如果您将 array_type
可视化为 int[3]
):
int[3]& f(int[3]& arr); //hypothetical
希望对您有所帮助。
int (&f (int (&arr)[3]) )[3]
{
return arr;
}
让我们从里面走吧。 (int (&arr)[3])
部分表示该函数将对 3 个元素的 int 数组的引用作为参数。这与正在 return 编辑的 arr
相同。
现在,语法的其余部分表示该函数应该 return 对 3 个整数数组的引用。 f
是函数的名称。 int &f()
意味着您 return 对 int
的引用,但您需要 return 固定大小的数组,因此您应该添加 [3]
使用 &f(...)
周围的括号是因为在 C++ 中,您将数组的大小写在变量名之后,而不是类型名之后,正如 Nawaz 在他的回答中所解释的那样。如果省略这些括号,编译器会将 f
解释为引用数组,如 int & f[3]
.
好吧,阅读这篇 article 关于 C 历史的文章,作者 Dennis M. Ritchie。
看起来像我们从 B、C 到 C++ 得到的这种语法...
我相信,这种声明一些 "basic type" 的多个变量的方式是这种奇怪语法的根源:
int a, *b, c[3];
所以 a
只是 int
,b
是指向 int
的指针,而 c
是 int
的数组...
如果这些 *
和 [3]
是类型定义的一部分而不是变量定义 - 那么我们需要 3 行来编写:
int a;
int* b;
int[3] c;
SO C page 上有两个很好的资源可用于学习如何解析此类结构:
- The Clockwise/Spiral Rule for parsing C declarations.
- cdecl: C gibberish ↔ English, a site that translate C expressions to readable English.
cdecl 有点失败 - 因为引用不是 C 的一部分 - 所以让我们尝试 The Clockwise/Spiral Rule for parsing C declarations.
int (&f(int (&arr)[3]))[3]
arr
-> arr&arr
-> arr 是引用(&arr)
-> arr 是参考 - 周围()
并没有真正改变什么(&arr)[3]
-> arr 是对大小为 3 的数组的引用int (&arr)[3]
-> arr 是对 int 类型的大小为 3 的数组的引用
下一个:
f
-> ff(int (&arr)[3])
-> f 是接受 arr 的函数,即 ...&f(int (&arr)[3])
-> f 是接受 arr 的函数,它是 ...,并返回引用(&f(int (&arr)[3]))[3]
-> f 是接受 arr 的函数,它是...,并返回对大小为 3 的数组的引用
int (&f(int (&arr)[3]))[3]
-> f 是接受 arr 的函数,arr 是对 int 类型大小为 3 的数组的引用,并返回对大小为 3 的 int 类型数组的引用
当然 - 至少对我而言,此代码应替换为更易于阅读的版本:
using int3 = int[3];
int3& f(int3& arr);