Argument passing by reference to pointer problem

谁都会走 提交于 2020-12-28 21:10:12

问题


Every time I try to compile my code I get error:

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

The test code looks like this:

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
}

I'd like to call that function in a single shot without creating a pointer somewhere only to pass it. And as pointers don't have constructors, something like this can't be done: set(int*(&myVal));

Is there any other way to pass a pointer by reference without needing to create a temporary variable?

Edit: By the way I know why the code fails to compile (I'm just passing the address which is possibly int and not an actual pointer). The question is how else can it be done.


回答1:


A reference to non-const cannot bind to an rvalue. The result of the & operator is an rvalue. Take a look at the difference between lvalues and rvalues or read a good C++ book.

Also, in your context, you don't need to pass by reference. The following is OK as well:

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

The reference would be needed if you were to do something like this;

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



回答2:


&myval is an rvalue (of type int*), because it's a temporary. It's a pointer, but you cannot modify it, because it's just created on the fly. Your function set however requires a non-const reference, so you cannot pass it a temporary.

By contrast, pMyVal is a named variable, thus an lvalue, so it can be passed as a non-constant reference.




回答3:


A very simple example can be found in this place. http://markgodwin.blogspot.de/2009/08/c-reference-to-pointer.html




回答4:


You can see the following sample code:

#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;
}

I installed Cygwin and used g++ to compile the above source code, binary file is out_pointer.exe. Executing out_pointer.exe, output is as follows:

$ ./out_pointer.exe

&ptrNumber = 0x28ac3c
ptrNumber = 0x800102c0
>>> *ptrNumber = 10

==================change(int*& ptr)====================
    &ptr = 0x28ac3c
    ptr  = 0x800102c0
=======================================================

<<< *ptrNumber = 100

From the above output, we see

&ptrNumber = &ptr

So, ptr is alias of ptrNumber. You can modify ptrNumber inside function void change(int*& ptr) by modifying ptr. For example, you can point ptr to another memory location as below:

#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;
}

New output:

$ ./out_pointer.exe

>>> &ptrNumber = 0x28ac3c
>>> ptrNumber = 0x800102c0
>>> *ptrNumber = 10

==================change(int*& ptr)====================
    &ptr = 0x28ac3c
    >>> ptr = 0x800102c0
    <<< ptr = 0x80048328
=======================================================

<<< &ptrNumber = 0x28ac3c
<<< ptrNumber = 0x80048328
<<< *ptrNumber = 20



回答5:


The problem is, int*&val can only be passed an lvalue, which the result of &myVal is not. By changing the signature to void set(int* const& val), it's telling the compiler you're not going to change the value of the pointer.

However, you normally wouldn't do that, only because if you're not going to change the value of the pointer, then passing the pointer by value is the most straightforward way to pass the value. And if you are going to change the value of the pointer, then you need to create a temporary to receive the result.



来源:https://stackoverflow.com/questions/7308384/argument-passing-by-reference-to-pointer-problem

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!