什么是引用指向指针?
What is a reference-to-pointer?
我最近看到一个函数被声明为:
void func(type* ¶m);
我已经知道type* param
和type& param
的区别。以上这些与他们有什么不同?什么时候用呢?这样做明智吗?
上面的操作不仅可以修改指向对象,还可以修改指针本身。例如,考虑下面的代码:
void func(int*& ptr) {
*ptr = 1;
ptr = 0;
}
int main() {
int x = 0;
int* y = &x;
func(y);
}
在执行结束时,x
的值为1
, y
的值为0
(如您所见)。
请注意,为了示例的缘故,我使用0
作为空指针,但如果您使用c++ 11,您可能应该使用nullptr
代替(它没有为std::ostream
重载operaror<<
)。
这个概念可以通过查看下面的代码来理解:
template<class Type> using ptr = Type*;
ptr<int>& x;
或
std::unique_ptr<int>& x;
在这些例子中,x
是对类型(ptr<int>
和std::unique_ptr<int>
)的引用,而类型恰好是具有指针语义(operator*
和operator->
)的指针/类。
关于指针中
const
限定符的位置,可以做一个可能有趣的题外话。考虑以下两个实例:
-
void func(const int*& ptr)
-
void func(int*const& ptr)
它们的含义是:
- 指针通过引用一个常量int。
- 指针,通过常量引用指向int。
按照上面与ptr
的类比,它们将是:
-
ptr<const int>&
-
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::optional
, std::unique_ptr
, std::shared_ptr
或std::reference_wrapper
)所取代。
让我们比较这三个选项:
-
void func(type* param); // 'param' is a 'type*' variable
-
void func(type& param); // 'param' is a reference to a 'type' variable
-
void func(type*& param); // 'param' is a reference to a 'type*' variable
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(¶m)
传递type param
的地址更安全。
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(¶m)
传递type* param
的地址,但是同样,出于上面提到的原因,它更安全。
- 如何使用基类指针引用派生类成员
- 将常量指针引用绑定到非常量指针
- 如果非动态变量被指针引用,何时超出范围?
- 转换指针引用的字符串
- 指针引用的生存期(以 C++为单位)
- 从 unique_ptr::get 发送指针作为指针引用进入函数
- 指针/引用的 CLion 格式
- 使用模板专用化来比较指针引用
- 如何保存指向抽象基类的指针/引用,但在 c++ 中仍然可以复制
- C++初始化指针/引用/复制细微差别
- 用数组或指针引用函数?
- 指针范围问题和返回类中封装的指针向量内的指针引用
- 强制转换为指针引用是否会导致未定义的行为
- 访问由 void 指针引用的结构的成员
- C 为什么当先前的步骤引发异常时,std :: shared_ptr的指针引用会被破坏
- 动态指针引用数组由三元运算符返回值,但有异常
- 悬空指向 int 和 char* 常量的指针/引用
- C++ 二维数组和指针引用
- 通过使用指针/引用,在C++中使用向量加快计算速度
- C++非类型模板模板到函数指针/引用