在 C + + 中传递对指针的引用

据我所知,没有理由不允许我在 C + + 中传递对指针的引用。然而,我的尝试失败了,我不知道为什么。

这就是我正在做的:

void myfunc(string*& val)
{
// Do stuff to the string pointer
}


// sometime later
{
// ...
string s;
myfunc(&s);
// ...
}

我得到了这个错误:

无法将参数1从‘ std: : string *’转换为‘ std: : string * &’

162367 次浏览

试试:

void myfunc(string& val)
{
// Do stuff to the string pointer
}


// sometime later
{
// ...
string s;
myfunc(s);
// ...
}

或者

void myfunc(string* val)
{
// Do stuff to the string pointer
}


// sometime later
{
// ...
string s;
myfunc(&s);
// ...
}

改成:

  std::string s;
std::string* pS = &s;
myfunc(pS);

编辑:

这被称为 ref-to-pointer,您不能传递临时地址作为函数的引用(除非它是 const reference)。

不过,我已经展示了 std::string* pS = &s;(指向局部变量的指针) ,它的典型用法是: 当您希望被调用方更改指针本身而不是它所指向的对象时。例如,一个分配内存的函数必须接受一个指针的引用,或者一个指向指针的指针:

void myfunc(string*& val)
{
//val is valid even after function call
val = new std::string("Test");


}

我知道传递指针的引用是可能的,我上周就这么做了,但是我不记得语法是什么了,因为你的代码现在在我脑子里看起来是正确的。然而,另一种选择是使用指针的指针:

Myfunc(String** s)

&s产生指向字符串的临时指针,您不能引用临时对象。

函数需要引用调用范围中的实际字符串指针,而不是匿名字符串指针。因此:

string s;
string* _s = &s;
myfunc(_s);

应该编译得很好。

但是,这只有在您打算修改传递给函数的指针时才有用。如果您打算修改字符串本身,您应该使用一个字符串的引用,如清酒建议。考虑到这一点,编译器抱怨原始代码的原因应该更加明显。在您的代码中,指针是“在运行中”创建的,修改该指针不会产生任何后果,而且这不是您的初衷。引用(相对于指针)的思想是,引用总是指向实际的对象。

问题是您试图将一个临时对象绑定到引用,除非引用是 const,否则 C + + 不允许这样做。

因此,您可以执行以下任一操作:

void myfunc(string*& val)
{
// Do stuff to the string pointer
}




void myfunc2(string* const& val)
{
// Do stuff to the string pointer
}


int main()
// sometime later
{
// ...
string s;
string* ps = &s;


myfunc( ps);   // OK because ps is not a temporary
myfunc2( &s);  // OK because the parameter is a const&
// ...


return 0;
}

编辑: 我做了一些实验,发现事情比我想象的要微妙一些。我现在认为这是一个准确的答案。

&s不是左值,因此您不能创建对它的引用,除非引用的类型是对 const的引用。例如,你不能

string * &r = &s;

但你可以

string * const &r = &s;

如果在函数头中放入类似的声明,那么它将工作。

void myfunc(string * const &a) { ... }

还有另一个问题,即临时工。规则是,只有当临时值为 const时,才能获得对它的引用。因此在这种情况下,人们可能会认为 & s 是临时的,因此必须在函数原型中声明为 const。从实际的角度来看,在这种情况下没有什么不同。(它要么是一个值,要么是一个临时值。无论哪种方式,都适用同样的规则。)然而,严格来说,我认为这不是暂时的,而是升值。我想知道是否有办法区分这两者。(可能只是简单地定义了所有临时值都是 rvalue,而所有非 lvalue 都是临时值。我不是这方面的专家。)

也就是说,你的问题可能是在一个更高的水平。为什么你想要一个参考的 s的地址?如果希望引用指向 s的指针,则需要定义如下所示的指针

string *p = &s;
myfunc(p);

如果您想要一个对 s的引用或者一个指向 s的指针,那么就直截了当地做吧。

Myfunc (“ string * & val”)这本身没有任何意义。“ string * & val”意味着“ string val”,* 和 & 相互取消。最后,不能将字符串变量转换为函数(“ string val”)。只能将基本数据类型传递给函数,因为其他数据类型需要作为指针或引用传递。 函数可以使用 string & val 或 string * val。

我刚刚使用了对指针的引用,使得除了根安全之外的所有指针都位于已删除的二叉树中。为了使指针安全,我们只需要将它设置为0。我不能使删除树的函数(只保留根)接受指向指针的 ref,因为我使用根(这个指针)作为向左和向右遍历的第一个输入。

void BinTree::safe_tree(BinTree * &vertex ) {
if ( vertex!=0 ) {  // base case
safe_tree(vertex->left);    // left subtree.
safe_tree(vertex->right);   //  right subtree.
// delete vertex;  // using this delete causes an error, since they were deleted on the fly using inorder_LVR. If inorder_LVR does not perform delete to the nodes, then, use delete vertex;
vertex=0;  // making a safe pointer
}
} // end in

底线是,当形式参数是(this)指针时,对指针的引用无效。

欢迎使用 C + + 11和 rvalue 引用:

#include <cassert>
#include <string>


using std::string;


void myfunc(string*&& val)
{
assert(&val);
assert(val);
assert(val->c_str());
// Do stuff to the string pointer
}


// sometime later
int main () {
// ...
string s;
myfunc(&s);
// ...
}

现在您可以访问指针的值(由 val引用) ,它是字符串的地址。

您可以修改指针,没有人会在意。这是右值首先是什么的一个方面。

注意: 指针的值只在 myfunc()返回之前有效。最后,它是一个临时的。