函数采用预期大小的数组,向用户发出信号
Function takes array of expected size, signalizing that to user
将函数声明为合法吗
void f (T arr[10]); // T is built-in type or class
向用户发出信号,告知其期望大小为10的数组?还是风格不好?
我知道传递数组总是通过指针来处理的,但最好让函数的用户知道——只需查看声明——传递的数组必须具有指定的大小,而用户不必阅读函数的整个文档。
将是
void f (T arr[10] = 0)
{
if (!arr)
// do stuff without array
else
// do stuff with array
}
也可以吗?f()
也可在不传递数组的情况下使用(默认参数0
)。
如果你真的只期望10个元素的C风格数组,
void f( int (&array)[10] );
将强制执行;任何试图传递除int [10]
以外的任何内容的行为将无法编译。
这方面的问题是:
如果调用者自己已经接收到数组作为参数,他没有遵守这个惯例,他不能给你打电话。你不能用指针调用此函数。
如果调用者有一个较大的数组,并且只希望您访问一个10元素的子数组,他不能给你打电话。
根据上下文的不同,这些问题可能是也可能不是真正的问题。
关于你的第二个无关问题:
void f( int arr[10] );
与完全相同
void f( int* arr );
并且可以为它提供相同的默认参数。
在一维数组的情况下,以下声明是等效的:
void f(int arr[10]);
void f(int* arr);
如果函数确实总是期望一个由10个元素组成的数组,那么第一个声明就是一个好的样式。
但是,请注意,在访问arr[9]
以外的元素时,它不会防止运行时错误。
在多维数组的情况下,以下声明是而不是等价的:
void f(int arr[][10]);
void f(int** arr);
第一个实际上告诉编译器如何"索引数组"。
因此,它不仅是一个好的样式,而且对于代码的正确工作也是必不可少的。
这是一种糟糕的风格。首先,它并没有真正检查传递数组的大小(你可以将int[20]
甚至int*
传递到这个函数中。其次,它可能会导致隐藏的错误,比如:
void f(int arr[10])
{
int other_array[10];
assert(sizeof(arr) == sizeof(other_arr)); // <- actually, the size is different
}
它只是将arr
视为一个指针。看看下面的代码:
void f (int arr[10])
{
cout<<sizeof(arr)/sizeof(arr[0]); //prints 1
}
main()
{
int arr[20];
cout<<sizeof(arr)/sizeof(arr[0]); //prints 20
f(arr);
}
对于第二部分,是的。如果没有传递任何参数,则指向int
(即arr
)的指针将为NULL
。
以下内容:
void f (int arr[10]);
似乎声明了一个函数,该函数按值接受10个int
s的数组,但它只是:
void f (int *arr);
也就是说,它是一个无声的杀手,可能很容易导致未定义的行为,就像下面的例子一样,试图访问超出阵列边界的内存:
#include <iostream>
void f (int arr[10]) {
arr[4] = 7;
}
int main() {
int a[2] = {1,2};
f(a);
}
通过指针或引用获取C样式数组可能更简单:
void f (int (&arr)[10]);
void f (int (*arr)[10]);
而且由于编译器会抱怨(关于前面的例子),所以不太容易出错:
类型为"int(&)[10]'的表达式中类型为"int(amp;)[10]"的引用的初始化无效
或在尝试用&a
:初始化指针的情况下
无法将参数"1"的"int()[2]"转换为"int()[10]"到"void f(int(*)[10])">
但我在这里看到的最合理的解决方案是避免完全使用C样式数组,而使用STL容器。如果大小是固定的,并且您支持C++11,则可以考虑使用std::array<int, 10>
,否则使用std::vector
:
#include <iostream>
#include <vector>
void f (std::vector<int> &vec) {
vec[4] = 7;
}
int main() {
std::vector<int> vec(10,0);
f(vec);
std::cout << vec[4];
}
- Qt VTK交互风格的信号到小部件
- C++如何通过用户输入删除列表元素
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何使用用户输入在C++中正确填充2D数组
- C++MySQL C api用户输入行
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何只允许用户输入正整数
- 如何在没有信号的情况下从C++执行QML插槽
- C++如何计算用户输入的数字中的偶数位数
- 通过for循环使用用户输入填充列表
- 当用户在qtablewidget中输入单元格时,如何获得信号?C++
- 函数采用预期大小的数组,向用户发出信号
- 当用户在tableView中用键盘箭头更改行时,如何发出信号
- 用户空间和内核空间进程中的信号处理程序集
- 用户类中的多签名信号管理
- 多用户信号量