通过引用传递参数到指针问题
Posted
技术标签:
【中文标题】通过引用传递参数到指针问题【英文标题】:Argument passing by reference to pointer problem 【发布时间】:2011-11-10 14:59:26 【问题描述】:每次我尝试编译我的代码时都会出错:
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 而不是实际指针的地址)。问题是还能怎么做。
【问题讨论】:
如果你不想创建一个指针,为什么你要求函数获取一个指针(通过引用)?为什么不set (int &v)v=10;
?
因为我的类正在存储值,但是该值随后作为指针传递给另一个存储该指针的类。这个指针必须通过引用函数中的指针参数来设置,否则传递的指针并不是真正指向值,而是指向它的副本。在设置此指针之前,我不想创建临时指针只是为了能够传递它。这就是为什么我没有介绍实际问题,而只是介绍了与我的问题相似且更容易的问题。
【参考方案1】:
对非常量的引用不能绑定到右值。 &
运算符的结果是一个右值。看看the difference between lvalues and rvalues 或阅读a good C++ book。
此外,在您的上下文中,您不需要通过引用传递。以下也可以:
void set (int *val)
*val = 10;
如果您要执行此类操作,则需要参考;
void set (int*& val)
val = new int; //notice, you change the value of val, not *val
*val = 10;
【讨论】:
所以int* const& p
是指向整数的常量指针的引用,所以它可以被赋值为右值,对吧?
@Raven:是的,这是正确的。但是不需要通过引用 const 来传递内置类型。它不如按值传递有效。对于用户定义的类型,最好通过引用来传递 const【参考方案2】:
问题是,int*&val
只能传递一个左值,而 &myVal 的结果不是。通过将签名更改为void set(int* const& val)
,它告诉编译器您不会更改指针的值。
但是,您通常不会这样做,只是因为如果您不打算更改指针的值,那么按值传递指针是传递值的最直接方式。如果你要改变指针的值,那么你需要创建一个临时的来接收结果。
【讨论】:
【参考方案3】:可以看到如下示例代码:
#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 的别名。您可以通过修改 ptr 来修改函数 void change(int*& ptr) 内的 ptrNumber。例如,您可以将 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
【讨论】:
【参考方案4】:在这个地方可以找到一个非常简单的例子。 http://markgodwin.blogspot.de/2009/08/c-reference-to-pointer.html
【讨论】:
【参考方案5】:&myval
是一个右值(int*
类型),因为它是一个临时值。它是一个指针,但您不能修改它,因为它只是动态创建的。但是,您的函数 set
需要非常量引用,因此您不能将其传递给临时函数。
相比之下,pMyVal
是一个命名变量,因此是一个左值,因此它可以作为非常量引用传递。
【讨论】:
我会说&myval
的类型是int * const &
。
抱歉,这在很多方面都是不正确和误导的。一方面,const int * &
是“对指向 const int 的指针的引用”,而不是“对常量指针的引用”。其次,对 const 和右值的引用是有区别的(右值 don't 的类型为 const T&
)。第三,对象不必被命名为左值。
@jpalecek:我没有说左值必须是命名对象,我说这个命名对象是左值。不是所有的猫……
&myval is of type int * const &
完全错误。 &myval
是 int*
类型的右值
@Kerrek:广告命名对象:我发现您的表述具有误导性,它表明“左值”是“命名对象”的同义词。你可以写“......是一个命名变量(它是一个左值)......”或其他东西。对于另一个问题,请阅读 Armen 所写的内容。以上是关于通过引用传递参数到指针问题的主要内容,如果未能解决你的问题,请参考以下文章