Передача ссылок на указатели в С++
Насколько я могу судить, нет причин, по которым мне не разрешено передавать ссылку на указатель на С++. Однако мои попытки сделать это неудачны, и я понятия не имею, почему.
Это то, что я делаю:
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 для функции.