【问题标题】:c++ Type error for fixed-size array being passed to template requesting array pointerc++ 固定大小数组的类型错误被传递给模板请求数组指针
【发布时间】:2021-12-01 13:53:42
【问题描述】:

我有一个如下模板函数:

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 的类型为 char [100]。无法将数组直接转换为“对字节数组指针的引用”,这是第一个示例尝试执行的操作(并且无效,因为对字节数组指针的引用不能转换为对byte * 的引用)。在第二个中,b 具有byte * 类型,因为发生了“数组到指针”转换(将数组的名称转换为指向其第一个元素的指针)。由于bbyte *,并且不是右值,因此它可以通过非const 引用传递给foo()

标签: c++ arrays templates


【解决方案1】:

第一种情况的错误是因为数组buffer没有衰减,因为你已经通过了它作为引用。也就是说,您不能将对指向字节的指针的引用绑定到字节数组。

而在第二种情况下,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&lt;int&gt;(buffer); 可以工作了。

【讨论】:

  • 我想修改 foo 中的缓冲区。这不可能吗?
  • @BobtheMagicMoose 你可以做到。因为您已经通过指针传递了缓冲区。
  • @BobtheMagicMoose 由于您已经将指针传递给数组,您可以使用该指针从函数内部修改数组。
  • 对不起,我的大脑被炸了。我的意思是说,我想修改指针。但是在阅读了每个人的有用 cmets 之后,看起来缓冲区不是指针,而是完全不同的动物(数组)。创建一个作为指针的新变量是唯一的选择。
  • @BobtheMagicMoose 如果要修改指针,则不能传递数组。您错误地相信了一个经常被告知的谎言,即指针是一个数组(现实情况是,在某些情况下,数组可以像指针一样使用,反之亦然)数组实际上不是一个指针,这是一种区分很重要的情况。
【解决方案2】:

这个问题与模板无关。将foo 更改为非模板void foo(byte* &amp;buffer),您将看到相同的错误。

函数中声明的

buffer 的类型是byte 指针的非const 引用。在您的第二篇文章中,buffer 是具有左值类别的byte[100] 类型。当分配给b 时,会发生衰减并且b 是具有左值类别的byte* 类型。所以b 可以毫无错误地传递给foo非常量引用可以绑定到非常量左值。您的第一篇文章不能以这种方式工作。两个简单的修复。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 2015-05-24
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    相关资源
    最近更新 更多