C++:二维数组引用?为什么这个功能有效
C++ : 2D array by reference? Why does this function work
参数printArray(int (&a)[n][m])是什么意思?为什么括号是必需的,为什么只需要向 printArray 函数提供 1 个值?该函数在调用时如何知道 n 和 m?
template <size_t n, size_t m>
void printArray(int (&a)[n][m]) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cout << a[i][j] << " ";
}
cout << endl;
}
}
int main(int argc, char* argv[])
{
cout << "Example I:" << endl;
int ab[2][5];
printArray(ab);
cout << "Example II:" << endl;
int b[2][5] = {{1, 2, 3}};
printArray(b);
cout << "Example III:"<< endl;
int c[][5] = {1, 2, 3, 4, 5, 6, 7};
printArray(c);
cout << "Example IV:" << endl;
int d[][5] = {{1, 2, 3, 4}, {5, 6}, {7}};
printArray(d);
}
它只是通过引用获取一个数组。至于传递的数组在函数内部的使用,您通常会编写与其他方式完全相同的代码。唯一的区别是它保留了它的数组类型。
当您将数组 "by value" 传递给一个函数时,它实际上会退化为指向其第一个元素的指针。通过引用(或地址)传递它可以防止这种用法的衰减。
事实上,即使你在参数中指定了第一个维度的范围,如果传递的是数组,编译器也会忽略它"by value"。
这是一个模板编程技巧,用于推断第一维的范围,否则如果您这样写就会丢失:
template<size_t m>
void printArray(int a[][m]) {...}
因此替代方案会变得不那么整洁,例如:
template<size_t m>
void printArray(int a[][m], size_t n) {...}
括号是必需的,因为int &a[n][m]
是一个二维引用数组,这是非法的,因为你不能创建一个引用数组。 int (&a)[n][m]
中的括号使这个 "reference to nxm array of int".
What does the parameter printArray(int (&a)[n][m])
mean?
表示a
是对int[n][m]
类型对象的引用。 int[n][m]
是 m
个 int[n]
类型对象的数组。 int[n]
是 n
个 int
类型对象的数组。因此,a
是对维度为 n
和 m
.
的二维数组的引用
n
和 m
是在 template <size_t n, size_t m>
中声明的模板参数。两个参数的类型都是size_t
,是一个整数类型。
Why are the parentheses necessary
因为 &-token 绑定到左边。 int&
是对 int 的引用。 int& a[n]
在语法上意味着 a
是一个引用数组(虽然这样的数组是不允许的)。圆括号用于消除 &-token 声明的是对 int 的(数组)引用还是对数组的引用。
and why does only 1 value need to be provided to the printArray function?
函数只有一个参数:a
。如果您传递一个可以绑定到适当类型的数组引用的值,那么它就可以工作。在你所有的例子中,参数都是二维整数数组,所以它们是正确的。
how does the function know n and m when called?
编译器知道,因为数组的大小是数组类型的一部分。并且由于模板参数推导。当未明确指定模板参数时,可以从函数的参数中推导出来。在这种情况下,如果您传递 int[2][5]
类型的参数,则 n
被推导为 2,m
被推导为 5。
您甚至可以添加一个模板类型参数并进行推导:
template <size_t n, size_t m, typename T>
void printArray(T (&a)[n][m])
如果要传递一个二维整数数组,T
将被推断为 int
。
if an array of references isn't allowed, why can't the compiler deduce that the parenthesis is not necessary.
如果 int &a[n]
表示对数组的引用,因为不能存在引用数组,那么程序员会感到困惑 int *a[n]
不是指向数组的指针,因为可以是指针数组。
此外,这会为不必要的引用添加特殊情况,从而使语言复杂化。
why isn't the form: printArray(int[n][m] &a)
更简单地说,为什么数组不能用 int[n] a
而不是 int a[n]
来声明。因为后一种语法是C语言的设计者(大概是Dennis Ritchie当时的)选择的。
参数printArray(int (&a)[n][m])是什么意思?为什么括号是必需的,为什么只需要向 printArray 函数提供 1 个值?该函数在调用时如何知道 n 和 m?
template <size_t n, size_t m>
void printArray(int (&a)[n][m]) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cout << a[i][j] << " ";
}
cout << endl;
}
}
int main(int argc, char* argv[])
{
cout << "Example I:" << endl;
int ab[2][5];
printArray(ab);
cout << "Example II:" << endl;
int b[2][5] = {{1, 2, 3}};
printArray(b);
cout << "Example III:"<< endl;
int c[][5] = {1, 2, 3, 4, 5, 6, 7};
printArray(c);
cout << "Example IV:" << endl;
int d[][5] = {{1, 2, 3, 4}, {5, 6}, {7}};
printArray(d);
}
它只是通过引用获取一个数组。至于传递的数组在函数内部的使用,您通常会编写与其他方式完全相同的代码。唯一的区别是它保留了它的数组类型。
当您将数组 "by value" 传递给一个函数时,它实际上会退化为指向其第一个元素的指针。通过引用(或地址)传递它可以防止这种用法的衰减。
事实上,即使你在参数中指定了第一个维度的范围,如果传递的是数组,编译器也会忽略它"by value"。
这是一个模板编程技巧,用于推断第一维的范围,否则如果您这样写就会丢失:
template<size_t m>
void printArray(int a[][m]) {...}
因此替代方案会变得不那么整洁,例如:
template<size_t m>
void printArray(int a[][m], size_t n) {...}
括号是必需的,因为int &a[n][m]
是一个二维引用数组,这是非法的,因为你不能创建一个引用数组。 int (&a)[n][m]
中的括号使这个 "reference to nxm array of int".
What does the parameter
printArray(int (&a)[n][m])
mean?
表示a
是对int[n][m]
类型对象的引用。 int[n][m]
是 m
个 int[n]
类型对象的数组。 int[n]
是 n
个 int
类型对象的数组。因此,a
是对维度为 n
和 m
.
n
和 m
是在 template <size_t n, size_t m>
中声明的模板参数。两个参数的类型都是size_t
,是一个整数类型。
Why are the parentheses necessary
因为 &-token 绑定到左边。 int&
是对 int 的引用。 int& a[n]
在语法上意味着 a
是一个引用数组(虽然这样的数组是不允许的)。圆括号用于消除 &-token 声明的是对 int 的(数组)引用还是对数组的引用。
and why does only 1 value need to be provided to the printArray function?
函数只有一个参数:a
。如果您传递一个可以绑定到适当类型的数组引用的值,那么它就可以工作。在你所有的例子中,参数都是二维整数数组,所以它们是正确的。
how does the function know n and m when called?
编译器知道,因为数组的大小是数组类型的一部分。并且由于模板参数推导。当未明确指定模板参数时,可以从函数的参数中推导出来。在这种情况下,如果您传递 int[2][5]
类型的参数,则 n
被推导为 2,m
被推导为 5。
您甚至可以添加一个模板类型参数并进行推导:
template <size_t n, size_t m, typename T>
void printArray(T (&a)[n][m])
如果要传递一个二维整数数组,T
将被推断为 int
。
if an array of references isn't allowed, why can't the compiler deduce that the parenthesis is not necessary.
如果 int &a[n]
表示对数组的引用,因为不能存在引用数组,那么程序员会感到困惑 int *a[n]
不是指向数组的指针,因为可以是指针数组。
此外,这会为不必要的引用添加特殊情况,从而使语言复杂化。
why isn't the form: printArray(int[n][m] &a)
更简单地说,为什么数组不能用 int[n] a
而不是 int a[n]
来声明。因为后一种语法是C语言的设计者(大概是Dennis Ritchie当时的)选择的。