将固定大小的数组传递给请求数组指针的模板时发生类型错误



我有一个模板函数,如下所示:

template<typename T>    
T foo(byte* &buffer){
...
}

当我尝试使用固定大小的数组访问它时,我得到一个错误:

byte buffer[100] = {};
foo<int>(buffer);

但是,当我从缓冲区创建一个新变量并传递它时,没有错误:

byte buffer[100] = {};
auto b = buffer;
foo<int>(b);

buffer的类型是什么?它不是一个byte*吗?是否有一种方法将其转换为byte*?这只会发生在模板函数中,否则它会按预期工作。

错误在第一种情况下,因为数组buffer不会腐烂因为你已经把它作为参考。也就是说,不能将指向byte的指针的引用绑定到字节数组。

而在第二种情况下,b是一个指针,可以通过引用传递。

解决方案1

解决这个问题的一种方法是从函数形参中删除引用,即通过实参的值删除引用。所以按值传递看起来像:
template<typename T>    
T foo(byte* buffer){//note pass by value
...
}

注意,在解决方案1中,您可以通过指针从函数内部修改数组。解决方案1的一个缺点是,这里你还可以指向其他指针(比如指向int的指针),所以你必须自己小心,不要试图访问任何超出数组边界的东西。另一种方法是按照最初的意图通过引用传递数组,如解决方案2所示。

解决方案2通过引用

传递数组
template<typename T,  std::size_t N>
T foo(byte (&buffer)[N])//this time you're passing the actual array by reference and not the pointer to its first element
{
}

现在在解决方案2中,你已经通过引用传递了数组,你可以直接在函数模板中修改它。现在foo<int>(buffer);可以工作了。

这个问题与模板无关。变化foonon-templatevoid foo(byte* &buffer),你会看到同样的错误。

函数中声明的buffer是指向byte的指针的非const引用类型. 在您的第二篇文章中,buffer类型为byte[100],具有l值类别。当分配给b时,发生衰减,b类型为byte*,具有l值类别。因此,可以将b传递给foo而不会出错。非const引用可以绑定到非const l值。你的第一篇文章不是这样写的。两个简单的修复。

  1. 更改为T foo(byte* buffer)。这样,当将buffer传递给foo时,首先发生衰减,导致类型为byte*的r值(将其视为未命名的临时中间结果)通过value传递给foo
  2. T foo(byte* const buffer)变化。同样,衰减先发生,const引用可以绑定到r值,而非const引用不能

如果您愿意,也可以将foo中的buffer声明为对byte[100]的非const引用类型。

最新更新