为什么这个模板化函数没有对数组进行零初始化编译?

Jer*_*ner 0 c++ templates

我正在尝试编写一个简单的模板化函数,它将数组的所有成员初始化为零(或者如果数组是一个对象数组,则将其初始化为默认构造状态).这是我写的:

template<typename T, int size> inline void ClearTheArray(T[size] theArray) 
{
   for (size_t i=0; i<size; i++) theArray[i] = T();
}
Run Code Online (Sandbox Code Playgroud)

...我的想法是,我可以将任何数组重置为其默认构造/全零状态,如下所示:

int myArray[6] = {1,2,3,4,5,6};
ClearTheArray(myArray);
// myArray now contains all zeroes

int * somePointer = myArray;
ClearTheArray(somePointer);  // compile error: somePointer doesn't contain array length info
Run Code Online (Sandbox Code Playgroud)

但是,上面没有编译; 相反,我theArray在正式参数列表的第一个实例中得到语法错误("expected')'").我在这做错了什么?有没有办法做到这一点?

Bri*_*ian 5

好吧,T[size] theArray根本就是不正确的声明语法.就像在任何其他上下文中声明数组时一样,名称在边界之前.那T theArray[size]将是正确的语法.

但是这仍然不会按照你想要它做的,因为数组不能通过值传递,并且尝试按值传递数组会导致它衰减为指针.编译器必须简单地重写参数声明T* theArray.这使得size无法推断,并允许您的函数接受任意指针.

要解决这些问题,您必须通过引用传递数组:

template<typename T, int size> inline void ClearTheArray(T (&theArray)[size]) 
{
   for (size_t i=0; i<size; i++) theArray[i] = T();
}
Run Code Online (Sandbox Code Playgroud)

然后您的示例用法将按预期运行.

然而,重新发明轮子是没有意义的.这样做的标准方法是

using std::begin;
using std::end;
std::fill(begin(myArray), end(myArray), 0);
std::fill(begin(somePointer), end(somePointer), 0);  // compile error
Run Code Online (Sandbox Code Playgroud)