我最近看到一个被声明为以下形式的函数:
void func(type* ¶m);
我已经知道了 type* param
和 type& param
的区别。那么上述内容与它们有何不同?何时使用这个?这样做是否明智?
我最近看到一个被声明为以下形式的函数:
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)
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' 是一个 '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(¶m)
来传递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(¶m)
传递type* param
的地址,但出于上述相同的原因,这样做更安全。请注意,我们保留了HTML标签。
type& param
完全相同,这里的类型是type*
。 - songyuanyao