【问题标题】:What's the use of pointer-casting a dereferenced pointer?指针转换解引用的指针有什么用?
【发布时间】:2011-10-01 21:20:32
【问题描述】:

这个问题是关于代码解释,而不是代码调试。我正在使用的代码有效。 我正在使用公共代码,我很想看看他们的“增长数组”模板之一,它看起来像这样:

  template <typename TYPE>
    TYPE *grow(TYPE *&array, int n, const char *name)
    {
      if (array == NULL) return create(array,n,name);

      bigint nbytes = ((bigint) sizeof(TYPE)) * n;
      array = (TYPE *) srealloc(array,nbytes,name);
      return array;
    }

而函数 srealloc 看起来像这样:

void *Memory::srealloc(void *ptr, bigint nbytes, const char *name)
{
  if (nbytes == 0) {
    destroy(ptr);
    return NULL;
  }

  ptr = realloc(ptr,nbytes);
  if (ptr == NULL) {
error();
  }
  return ptr;
}

请暂时忽略创建功能。我的主要问题是为什么他们在模板中进行指针转换和取消引用array?这样做有什么好处?如果他们根本没有*&amp; 怎么办?

谢谢!

【问题讨论】:

    标签: c++ pointers dereference


    【解决方案1】:

    &amp; 标记有很多含义,您在这里混淆了其中两个含义。你并不孤单!作为操作员,它的意思是“地址”,您似乎对此感到满意(来自C)。但作为类型限定符,它的意思是“引用”,这是完全不同的。第一个意思:

    int x ;
    int* p = &x ; // p = address of x (as in C)
    

    第二个意思:

    void f (int& x) { // x is a reference to an int -- its address is passed to f
      x++ ;
    }
    ...
    int y = 99 ;
    f (y) ; // After this call, y is equal to 100
    

    在本例中,代码等价于

    void f (int* x) {
      (*x)++ ;
    }
    ...
    int y = 99 ;
    f (&y) ; // After this call, y is equal to 100
    

    这段代码看起来不太干净,但对于C 程序员来说更容易理解。

    所以...函数声明

    void f (int*& p) ;
    

    (如您的示例)意味着f 可以更改调用函数传递的int* 参数的值。你的示例代码对我来说有点奇怪,因为如果它可以直接更改参数,为什么它需要返回 array 的新值?但这是一个风格问题,我已经学会了不要在这里讨论这些问题:-)

    【讨论】:

    • 感谢这些示例和说明,这非常有帮助。只是为了我正确理解你,这些函数是否可以在没有return 的情况下工作,因为它们已经直接更改了参数?
    • 您介意看看我在下面对@DannisZickefoose 的评论吗?
    【解决方案2】:
    *&
    

    不是“指针解引用”。它是对指针的引用。它是必需的,因此增长函数可以更改指针,而不仅仅是指针指向的内容。另一种方法是指向指针的指针,如以下代码所示。

    template <typename TYPE>
    TYPE *grow(TYPE **array, int n, const char *name)
    {
      if ((*array) == NULL) return create((*array),n,name);
    
      bigint nbytes = ((bigint) sizeof(TYPE)) * n;
      (*array) = (TYPE *) srealloc((*array),nbytes,name);
      return *array;
    }
    

    【讨论】:

    • 我了解替代方案与问题中当前示例的相同之处,我只是不明白为什么有必要。为什么不能是TYPE array,因为array 已经是[size] * 类型,其中[size] 是intdouble 等。
    • @Amit:如果可能的话,看起来这是为了重新分配一个数组。如果不能,它会分配一个全新的数组并将所有内容移过来。在后一种情况下,原始指针最终变得毫无价值,因此立即更新它更安全。这暗示了一个参考参数。但是,内存分配函数通常会返回它们分配的内存地址。作者可能只是想确保这两种方法都可用;前者是为了安全,后者是为了一致性。
    • @DennisZickefoose:感谢您的评论——这很有帮助。谢谢!!
    • @DennisZickefoose:如果我写了一个类似的函数,但只定义了TYPE array,并为我的grow 函数定义了return array。它还能完成同样的功能吗?
    • @Amit:你的意思是TYPE* array。但是,是的,只要您只使用array = grow (array, n, name); 调用它,它就会完成相同的功能
    猜你喜欢
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    相关资源
    最近更新 更多