Вопрос

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

Вот что я делаю:

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

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

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

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

Это было полезно?

Решение

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

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

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

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

Другие советы

Проблема в том, что вы пытаетесь привязать временную ссылку к ссылке, которую C ++ не разрешает, если ссылка не является 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;
}

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

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

РЕДАКТИРОВАТЬ:

Это называется 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");

}

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

Пытаться:

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);
    // ...
}

РЕДАКТИРОВАТЬ: Я экспериментировал с некоторыми, и обнаружил, что вещи немного тоньше, чем я думал. Вот то, что я сейчас считаю точным ответом.

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

string * &r = &s;

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

string * const &r = &s;

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

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

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

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

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

Если вам нужна ссылка на s или указатель на s , сделайте это просто.

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

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).

Добро пожаловать в C ++ 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 () не вернется. Наконец, это временно.

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

Myfunc(String** s)

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top