Передача аргумента по ссылке на проблему с указателем - PullRequest
4 голосов
/ 05 сентября 2011

Каждый раз, когда я пытаюсь скомпилировать свой код, я получаю сообщение об ошибке:

не может преобразовать параметр 1 из 'int *' в 'int * &'

Это тестовый код, похожий на этот:

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

int main(){
   int myVal;
   int *pMyVal = new int;
   set(&myVal); // <- this cause trouble
   set(pMyVal); // <- however this doesn't
}

Я бы хотел вызвать эту функцию в одном кадре, не создавая указатель где-то по одной причине, чтобы передать его. И поскольку у указателей нет конструктора, что-то подобное не может быть сделано. set(int*(&myVal));. Есть ли другой способ передать указатель по ссылке без необходимости создания временной переменной?

Редактировать: Кстати, я знаю, почему код не компилируется (я просто передаю адрес, который, возможно, int, а не фактический указатель). Вопрос в том, как еще это сделать.

Ответы [ 5 ]

13 голосов
/ 05 сентября 2011

Ссылка на неконстантную не может привязываться к r-значению. Результат оператора & является rvalue. Взгляните на разницу между lvalues ​​и rvalues ​​ или прочитайте хорошую книгу по 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;
}
2 голосов
/ 05 сентября 2011

&myval - это значение (типа int*), потому что оно временное.Это указатель, но вы не можете изменить его, потому что он просто создан на лету.Однако ваша функция set требует неконстантной ссылки, поэтому вы не можете передать ее временно.

В отличие от этого, pMyVal является именованной переменной, то есть lvalue, поэтому ее можно передавать как непостоянная ссылка.

0 голосов
/ 26 августа 2014

Вы можете увидеть следующий пример кода:

#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.Вы можете изменить ptrNumber внутри функции void change (int * & ptr), изменив 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
0 голосов
/ 07 сентября 2013

Очень простой пример можно найти в этом месте.http://markgodwin.blogspot.de/2009/08/c-reference-to-pointer.html

0 голосов
/ 05 сентября 2011

Проблема в том, что int*&val может быть передано только значение lvalue, что не является результатом & myVal. Изменение подписи на void set(int* const& val) говорит компилятору, что вы не собираетесь изменять значение указателя.

Однако обычно вы этого не сделаете, только потому, что если вы не собираетесь изменять значение указателя, то передача указателя по значению является наиболее простым способом передачи значения. И если вы собираетесь изменить значение указателя, то вам нужно создать временный для получения результата.

...