什么是指向指针的引用?

11

我最近看到一个被声明为以下形式的函数:

void func(type* &param);

我已经知道了 type* paramtype& param 的区别。那么上述内容与它们有何不同?何时使用这个?这样做是否明智?


10
这与 type& param 完全相同,这里的类型是 type* - songyuanyao
2个回答

19

以上操作不仅可以修改所指向的对象,还可以修改指针本身。例如,考虑以下代码:

void func(int*& ptr) {
    *ptr = 1;
    ptr = 0;
}

int main() {
    int x = 0;
    int* y = &x;
    func(y);
}

执行完毕之后,x的值为1y的值为0(如您所见)。

请注意,为了举例说明,我使用了0作为空指针,但如果您使用的是C++11,您应该使用nullptr(它没有一个重载的std::ostreamoperaror<<)。


可以通过查看以下代码来理解此概念:

template<class Type> using ptr = Type*;
ptr<int>& x;
或者
std::unique_ptr<int>& x;
在这些示例中,x是一个类型的引用(先是ptr<int>,然后是std::unique_ptr<int>),它碰巧是一个具有指针语义的指针/类(operator*operator->)。
可能会对指针中的const限定符位置产生兴趣。考虑以下两种情况:
  1. void func(const int*& ptr)
  2. void func(int*const& ptr)
它们的含义是:
  1. 指向常量整数的指针引用
  2. 指针常量引用到整数
按照上面与ptr的类比,它们将分别是:
  1. ptr<const int>&
  2. ptr<int> const&
因此,第一种情况在函数体内执行*ptr = 1将失败(因为int是常量),但可以愉快地执行ptr = 0
第二种情况相反,允许*ptr = 1(因为指向的int不是常量),而不允许ptr = 0(因为指针是常量)。
当然,在以下情况下:
void func(const int*const& ptr)

ptr 比喻中,这个语法会是 ptr<const int> const&,两者都不被允许。


什么时候使用它?使用它是明智的吗?

就像每个特性一样,当你需要它时才会发现其有用。但作为一个一般的想法,有些人使用它来在释放动态分配的资源后重置指针(我不建议这样做,见下文)。

我们来看一个例子:

free_my_int(int*& ptr) {
    delete ptr;
    ptr = nullptr;
}

int* x = new int(42);
free_my_int(x);

在执行结束时,x将被正确释放,并自动设置指针为nullptr(空指针)。这是为了防止由于缺少ptr = nullptr而导致的丑陋的分段错误或“已释放的指针未被分配”的错误消息。

但是,在C ++ 11和C ++ 14中,使用指针的情况非常少,甚至对指向指针的引用的使用更少。大部分指针用于的事情都可以用其他标准构造替代(例如std::optionalstd::unique_ptrstd::shared_ptrstd::reference_wrapper)。


2

让我们比较这三种选项:

  • void func(type* param); // 'param' 是一个 'type*' 变量
  • void func(type& param); // 'param' 是一个指向 'type' 变量的引用
  • void func(type*& param); // 'param' 是一个指向 'type*' 变量的引用

void func(type* param)
{
    type x;
    ...
    param = &x;
    // Argument 'param' is regarded as a local variable in this function,
    // so setting 'param = ...' will have no effect outside this function
}

当然,如果你执行*param = ...,那么它会影响指向param的内存内容。例如,你也可以执行param[5] = ...,并影响该内存空间中的其他区域。
void func(type& param)
{
    type x;
    ...
    param = x;
    // Argument 'param' is regarded as a reference to a variable outside this
    // function, so setting 'param = ...' will effect the referenced variable
}

在这里,你只会改变所引用的变量本身,因此比声明函数为void func(type* param),然后通过调用func(&param)来传递type param的地址更安全。请注意保留HTML标签。
void func(type*& param)
{
    type x;
    ...
    param = &x;
    // Argument 'param' is regarded as a reference to a variable outside this
    // function, so setting 'param = ...' will effect the referenced variable
}

这类似于声明函数为void func(type** param),然后通过调用func(&param)传递type* param的地址,但出于上述相同的原因,这样做更安全。请注意,我们保留了HTML标签。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接