7

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.

2
  • If you don't want to create a pointer, why do you require the function to take a pointer (by reference)? Why not set (int &v){v=10;}? Commented Sep 5, 2011 at 12:57
  • Because my class is storing value, but this value is then passed as pointer to another class which stores this pointer. This pointer must be set by reference to pointer argument in function that does it, because otherwise the passed pointer isn't really pointing to value, but to it's copy. And before setting this pointer I don't want to create temporary pointer just to be able to pass it.. That's why I didn't introduce actual problem, but only that which resembles my it and is way more easy. Commented Sep 5, 2011 at 13:10

5 Answers 5

16

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;
}
Sign up to request clarification or add additional context in comments.

2 Comments

so int* const& p is reference to constant pointer to integer, and so it can be assigned rvalue, right?
@Raven: Yes, that is correct. But no need to pass built-in types by reference to const. It's less effective than passing by value. For User-Defined Types, it's better to pass by reference-to const
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.

9 Comments

I'd say &myval is of type int * const &.
Sorry, but this is incorrect and misleading in many ways. For one, const int * & is a "reference to a pointer to const int", not a "reference to constant pointer". Second, there is a distinction between references to const and rvalues (rvalues don't have type const T&). Third, an object need not be named to be a lvalue.
@jpalecek: I didn't say lvalues have to be named objects, I said that this named object is an lvalue. Not all cats...
&myval is of type int * const & is plain wrong. &myval is an rvalue of type int*
@Kerrek: ad named objects: I find your formulation misleading, it indicates that "lvalues" are synonymous to "named objects". You could have written "... is a named variable (which is an lvalue) ..." or something. To the other issue, read what Armen wrote.
|
0

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

Comments

0

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

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.