通过指针引用传递参数的问题

Argument passing by reference to pointer problem

本文关键字:参数 问题 指针 引用      更新时间:2023-10-16

每次我试图编译我的代码,我得到错误:

cannot convert parameter 1 from 'int *' to 'int *&'

测试代码看起来像这样:

void set (int *&val){
   *val = 10;
}
int main(){
   int myVal;
   int *pMyVal = new int;
   set(&myVal); // <- this causes trouble
   set(pMyVal); // <- however, this doesn't
}

我想调用这个函数在一个单一的镜头没有创建一个指针,只是传递它的地方。由于指针没有构造函数,所以不能这样做:set(int*(&myVal));

是否有其他方法通过引用传递指针而不需要创建临时变量?

编辑:顺便说一下,我知道为什么代码无法编译(我只是传递可能是int而不是实际指针的地址)。

对非const的引用不能绑定到右值。&运算符的结果是一个右值。看看左值和右值的区别,或者读一本好的c++书。

同样,在您的上下文中,您不需要通过引用传递。下面也是可以的:

void set (int *val){
   *val = 10;
}

如果您要做这样的事情,则需要引用;

void set (int*& val){
   val = new int; //notice, you change the value of val, not *val
   *val = 10;
}

&myval是右值(类型为int*),因为它是临时的。它是一个指针,但你不能修改它,因为它是动态创建的。但是你的函数set需要一个非const引用,所以你不能给它传递一个临时的。

相比之下,pMyVal是一个命名变量,因此是左值,所以它可以作为一个非常量引用传递。

在这里可以找到一个非常简单的例子。http://markgodwin.blogspot.de/2009/08/c-reference-to-pointer.html

您可以看到以下示例代码:

#include <iostream>
using namespace std;
void change(int*& ptr) {
    cout << endl;
    cout << "==================change(int*& ptr)====================" << endl;
    cout << "    &ptr = " << &ptr << endl;
    cout << "    ptr  = " << ptr << endl;
    cout << "=======================================================" << endl;
    cout << endl;
    *ptr *= *ptr;
}
int main(void) {
    int* ptrNumber = new int(10);
    cout << endl;
    cout << "&ptrNumber = " << &ptrNumber << endl;
    cout << "ptrNumber = " << ptrNumber << endl;
    cout << ">>> *ptrNumber = " << *ptrNumber << endl;
    change(ptrNumber);
    cout << "<<< *ptrNumber = " << *ptrNumber << endl;
}

我安装了Cygwin,用g++编译了上面的源代码,二进制文件为out_pointer.exe。执行out_pointer.exe,输出如下:

$ ./out_pointer.exe
&ptrNumber = 0x28ac3c
ptrNumber = 0x800102c0
>>> *ptrNumber = 10
==================change(int*& ptr)====================
    &ptr = 0x28ac3c
    ptr  = 0x800102c0
=======================================================
<<< *ptrNumber = 100
从上面的输出中,我们看到
&ptrNumber = &ptr

所以ptr是ptrNumber的别名。你可以在函数里面修改ptrNumberPtr)通过修改Ptr。例如,可以将ptr指向另一个内存位置,如下所示:

#include <iostream>
using namespace std;
void change(int*& ptr) {
    cout << endl;
    cout << "==================change(int*& ptr)====================" << endl;
    cout << "    &ptr = " << &ptr << endl;
    cout << "    >>> ptr = " << ptr << endl;
    ptr = new int(20);
    cout << "    <<< ptr = " << ptr << endl;
    cout << "=======================================================" << endl;
    cout << endl;
}
int main(void) {
    int* ptrNumber = new int(10);
    cout << endl;
    cout << ">>> &ptrNumber = " << &ptrNumber << endl;
    cout << ">>> ptrNumber = " << ptrNumber << endl;
    cout << ">>> *ptrNumber = " << *ptrNumber << endl;
    change(ptrNumber);
    cout << "<<< &ptrNumber = " << &ptrNumber << endl;
    cout << "<<< ptrNumber = " << ptrNumber << endl;
    cout << "<<< *ptrNumber = " << *ptrNumber << endl;
}
新输出:

$ ./out_pointer.exe
>>> &ptrNumber = 0x28ac3c
>>> ptrNumber = 0x800102c0
>>> *ptrNumber = 10
==================change(int*& ptr)====================
    &ptr = 0x28ac3c
    >>> ptr = 0x800102c0
    <<< ptr = 0x80048328
=======================================================
<<< &ptrNumber = 0x28ac3c
<<< ptrNumber = 0x80048328
<<< *ptrNumber = 20

问题是,int*&val只能传递一个左值,而&myVal的结果不是。通过将签名更改为void set(int* const& val),它告诉编译器您不打算更改指针的值。

然而,你通常不会这样做,只是因为如果你不打算改变指针的值,那么按值传递指针是最直接的传递值的方式。如果要更改指针的值,则需要创建一个临时对象来接收结果