【问题标题】:Why can't we pass int array[] to hoo(int* &p)?为什么我们不能将 int array[] 传递给 hoo(int* &p)?
【发布时间】:2019-01-09 19:34:31
【问题描述】:

据我了解,int array[]={1,2,3,4,5} 中的array 只是指向array 的第一个元素的指针。这意味着可以将array 分配给int* 类型的指针ptr

hoo 中的参数int* &p 将通过引用传递参数。这意味着我们可以将传递的参数更改为指向hoo 中的另一个值。

void hoo(int* &p, int n)
{
    for (int i = 0; i < n; i++)
        cout << p[i] << endl;
}

int main()
{
    int array[] = { 1,2,3,4,5 };

    // I can do this
    int* ptr = array;
    hoo(ptr, 5);

    // but not this.
    //hoo(array, 5);
}

问题

为什么我们不能在没有 ptr 的情况下将 int array 传递给 hoo

【问题讨论】:

  • "hoo 中的参数int* &amp;p 将通过引用传递参数。这意味着我们可以将传递的参数更改为指向hoo 中的另一个值。" i> 如果你试图在hoo 中做p=nullptr 怎么办? array 的预期结果是什么?
  • 数组不是指向其第一个元素的指针。您的标题提出的问题与您的问题文本完全不同。您可以int[] 传递给int*,但不能传递给int*&amp;
  • @tkausl 我编辑了问题标题,它使您的部分评论无效。
  • 数组不是指针,句号。如果您将数组视为真正的数组,它将为您省去很多麻烦。是的,在大多数情况下它可以衰减为指针,但不要将其视为指针。此外,您可以停止使用原始数组并使用std:array 代替它们。他们会让这样的问题消失。
  • 您是否正在尝试解决一些真正的问题,或者这只是为了学习目的?无论哪种情况,请使用 std::arraystd::vector

标签: c++ arrays pointers reference lvalue


【解决方案1】:

在我的理解中, int array[]={1,2,3,4,5} 中的数组只是指向数组第一个元素的指针。

这是不正确的。数组是数组,指针是指针。它们是具有不同属性的不同类型。他们经常感到困惑,因为数组具有会急切地衰减为指向其第一个元素的指针的属性。

hoo(array, 5); 尝试将array 转换为int*,但该转换的结果是一个右值,不能绑定到非const 引用。例如,如果您将 hoo 更改为使用 const 引用,它将编译得很好:

void hoo(int* const &p, int n) { }

int main()
{
    int array[] = { 1,2,3,4,5 };
    hoo(array, 5);
}

在这种情况下,您无法更改 what p 指向的内容,从而使引用的使用毫无意义。

【讨论】:

    【解决方案2】:

    当函数采用int* &amp; 参数时,即对指向int 的指针的(非移动)引用 - 那么需要有一个真正的指针变量,该引用是指。它不能是临时指针值。因此你不能这样做:

    int x;
    hoo(&x, 123);
    

    因为没有指针变量可以引用——只是临时变量。这与您的int[5] 基本相同。实际上任何地方都没有int* 变量——只有5 个ints。当您将array 传递给hoo() 时,C++ 对该标识符所做的就是array-to-pointer decay:它实际上传递了&amp;(array[0])。所以就像前面的例子一样,它不会编译。

    【讨论】:

      【解决方案3】:

      其他答案已经解释了这个问题。我想建议改变编码习惯。

      使用void hoo(int* &amp;p, int n) 作为函数声明是非常非常古老的风格。使用模板,您可以让编译器推断大小并获取对数组的引用,这样就不需要使用指针了。

      template <size_t N>
      void hoo( int (&p)[N]) // The argument is a reference to an array of N elements.
      {
          for (int i = 0; i < N; i++)
              cout << p[i] << endl;
      }
      

      对函数的调用变得自然。

      int array[] = { 1,2,3,4,5 };
      hoo(array);
      

      如果您的函数也需要能够支持动态分配的数组,您可以按如下方式重载该函数。

      void hoo(int* p, size_t N)
      {
          for (int i = 0; i < N; i++)
              cout << p[i] << endl;
      }
      
      template <size_t N>
      void hoo( int (&p)[N]) // The argument is a reference to an array of N elements.
      {
          hoo(p, N);
      }
      

      【讨论】:

      • 它不会接受动态分配的数组,所以它的用途非常有限。
      • @Slava,真的。更新了答案。
      猜你喜欢
      • 2017-12-11
      • 1970-01-01
      • 1970-01-01
      • 2022-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-03
      相关资源
      最近更新 更多