我有一个模板函数,如下所示:
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);
可以工作了。
这个问题与模板无关。变化foo
non-templatevoid foo(byte* &buffer)
,你会看到同样的错误。
函数中声明的buffer
是指向byte
的指针的非const引用类型. 在您的第二篇文章中,buffer
类型为byte[100]
,具有l值类别。当分配给b
时,发生衰减,b
类型为byte*
,具有l值类别。因此,可以将b
传递给foo
而不会出错。非const引用可以绑定到非const l值。你的第一篇文章不是这样写的。两个简单的修复。
- 更改为
T foo(byte* buffer)
。这样,当将buffer
传递给foo
时,首先发生衰减,导致类型为byte*
的r值(将其视为未命名的临时中间结果)通过value传递给foo
。 T foo(byte* const buffer)
变化。同样,衰减先发生,const引用可以绑定到r值,而非const引用不能。
如果您愿意,也可以将foo
中的buffer
声明为对byte[100]
的非const引用类型。