Передача ссылок на указатели в С++

Насколько я могу судить, нет причин, по которым мне не разрешено передавать ссылку на указатель на С++. Однако мои попытки сделать это неудачны, и я понятия не имею, почему.

Это то, что я делаю:

void myfunc(string*& val)
{
    // Do stuff to the string pointer
}

// sometime later 
{
    // ...
    string s;
    myfunc(&s);
    // ...
}

И я получаю эту ошибку:

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

Ответ 1

Ваша функция ожидает ссылки на фактический указатель строки в области вызова, а не на анонимный указатель строки. Таким образом:

string s;
string* _s = &s;
myfunc(_s);

должен компилироваться просто отлично.

Однако это полезно только в том случае, если вы намерены изменить указатель, который вы передаете функции. Если вы намерены изменить строку, вы должны использовать ссылку на строку, как предложил Sake. Имея это в виду, должно быть более очевидно, почему компилятор жалуется на ваш исходный код. В вашем коде указатель создается "на лету", изменяя, что указатель не имеет никакого значения, и это не то, что предназначено. Идея ссылки (по сравнению с указателем) заключается в том, что ссылка всегда указывает на фактический объект.

Ответ 2

Проблема заключается в том, что вы пытаетесь привязать временную ссылку, которую С++ не разрешает, если ссылка не указана const.

Итак, вы можете сделать одно из следующих действий:

void myfunc(string*& val)
{
    // Do stuff to the string pointer
}


void myfunc2(string* const& val)
{
    // Do stuff to the string pointer
}

int main()
// sometime later 
{
    // ...
    string s;
    string* ps = &s;

    myfunc( ps);   // OK because ps is not a temporary
    myfunc2( &s);  // OK because the parameter is a const&
    // ...

    return 0;
}

Ответ 3

Измените его на:

  std::string s;
  std::string* pS = &s;
  myfunc(pS);

EDIT:

Это называется ref-to-pointer, и вы не можете передавать временный адрес в качестве ссылки на функцию. (если это не const reference).

Хотя, я показал std::string* pS = &s; (указатель на локальную переменную), его типичное использование: когда вы хотите, чтобы вызывающий менял сам указатель, а не объект, на который он указывает. Например, функция, которая выделяет память и назначает адрес блока памяти, который она назначила для своего аргумента, должна ссылаться на указатель или указатель на указатель:

void myfunc(string*& val)
{
//val is valid even after function call
   val = new std::string("Test");

}

Ответ 4

&s создает временный указатель на строку, и вы не можете ссылаться на временный объект.

Ответ 5

Try:

void myfunc(string& val)
{
    // Do stuff to the string pointer
}

// sometime later 
{
    // ...
    string s;
    myfunc(s);
    // ...
}

или

void myfunc(string* val)
{
    // Do stuff to the string pointer
}

// sometime later 
{
    // ...
    string s;
    myfunc(&s);
    // ...
}

Ответ 6

EDIT: Я экспериментировал с некоторыми, и обнаруженная вещь немного более тонкая, чем я думал. Вот то, что я сейчас думаю, является точным ответом.

&s не является значением lvalue, поэтому вы не можете создать ссылку на него, если тип ссылки не ссылается на const. Так, например, вы не можете делать

string * &r = &s;

но вы можете сделать

string * const &r = &s;

Если вы поместите аналогичное объявление в заголовок функции, оно будет работать.

void myfunc(string * const &a) { ... }

Есть еще одна проблема, а именно временные. Правило заключается в том, что вы можете получить ссылку на временное, только если оно const. Поэтому в этом случае можно утверждать, что & s является временным и поэтому должно быть объявлено const в прототипе функции. С практической точки зрения это не имеет никакого значения в этом случае. (Это либо rvalue, либо временное. В любом случае применяется то же правило). Однако, строго говоря, я считаю, что это не временный, а rvalue. Интересно, есть ли способ различать эти два. (Возможно, просто определено, что все временные значения являются значениями r, а все не-lvalues ​​являются временными. Я не эксперт по стандарту.)

Как говорится, ваша проблема, вероятно, на более высоком уровне. Зачем вам нужна ссылка на адрес s? Если вы хотите ссылку на указатель на s, вам нужно определить указатель, как в

string *p = &s;
myfunc(p);

Если вам нужна ссылка на s или указатель на s, выполните прямую вещь.

Ответ 7

Я только что использовал ссылку на указатель, чтобы сделать все указатели в удаленном двоичном дереве, кроме безопасного для root. Чтобы сделать указатель безопасным, нам просто нужно установить его равным 0. Я не мог заставить функцию, которая удаляет дерево (сохраняя только корень), чтобы принять ref для указателя, поскольку я использую корень (этот указатель) в качестве первого вход для перемещения влево и вправо.

void BinTree::safe_tree(BinTree * &vertex ) {
    if ( vertex!=0 ) {  // base case
        safe_tree(vertex->left);    // left subtree.
            safe_tree(vertex->right);   //  right subtree.
          // delete vertex;  // using this delete causes an error, since they were deleted on the fly using inorder_LVR. If inorder_LVR does not perform delete to the nodes, then, use delete vertex;
        vertex=0;  // making a safe pointer
    }
} // end in

Нижняя строка, ссылка на указатель недействительна, когда формальный параметр является указателем (this).

Ответ 8

Добро пожаловать в С++ 11 и ссылки rvalue:

#include <cassert>
#include <string>

using std::string;

void myfunc(string*&& val)
{
    assert(&val);
    assert(val);
    assert(val->c_str());
    // Do stuff to the string pointer
}

// sometime later 
int main () {
    // ...
    string s;
    myfunc(&s);
    // ...
}

Теперь у вас есть доступ к значению указателя (на которое указывает val), который является адресом строки.

Вы можете изменить указатель, и никто не будет заботиться. Это один из аспектов того, что rvalue в первую очередь.

Будьте осторожны: значение указателя действует только до тех пор, пока myfunc() не вернется. Наконец, это временное.

Ответ 9

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

Myfunc(String** s)

Ответ 10

myfunc ( "string * & val" ), это само по себе не имеет никакого смысла. "string * & val" подразумевает "string val", * и и отменяет друг друга. Наконец, нельзя использовать переменную string для функции ( "string val" ). К функции могут быть переданы только базовые типы данных, поскольку другие типы данных должны передаваться в виде указателя или ссылки. Вы можете иметь либо строку & val или string * val для функции.