C ++でポインターへの参照を渡す


130

私の知る限り、C ++でポインターへの参照を渡すことを許可してはならない理由はありません。しかし、私の試みは失敗しており、その理由はわかりません。

これは私がやっていることです:

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

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

そして私はこのエラーを得ています:

パラメータ1を 'std :: string *'から 'std :: string *&'に変換できません

回答:


126

関数は、匿名の文字列ポインターではなく、呼び出しスコープ内の実際の文字列ポインターへの参照を期待しています。したがって:

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

うまくコンパイルできるはずです。

ただし、これは、関数に渡すポインターを変更する場合にのみ役立ちます。文字列自体を変更するつもりなら、酒が提案したように文字列への参照を使用する必要があります。これを念頭に置くと、コンパイラが元のコードについて文句を言う理由がより明確になるはずです。あなたのコードでは、ポインターは「オンザフライ」で作成され、そのポインターを変更しても何の影響もなく、それは意図されたものではありません。参照(対ポインター)の考え方は、参照は常に実際のオブジェクトを指すということです。


86

問題は、一時変数を参照にバインドしようとしていることです。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;
}

例2でバー氏がするようにタイプを書き出すことは特にstring* const& val有益const string* &valです。たとえば、のような判読しにくい同等のものではありません。私の目には、これは明らかに、const 参照、ポインタ、文字列への参照です。私は個人的T const&にはconst T&、この正確な説明を得るために、宣言ではなく書くことを好みます。
fish2000

1
Nit pick(批判ではありません):私にとって、bind a temporary to the referenceこの答えのフレーズは@Chris 'よりも明確reference to an actual string pointer in the calling scope, not an anonymous string pointerです。とにかく、どちらも私の見解では正しいと思われます。
kevinarpe

1
@ fish2000それだけではなく、const string*&そしてstring* const&実際には異なる種類があります。1つ目はへの非const参照const string*ですが、2つ目はへのconst参照string*です。
ジャスティン時間-2016年

@ fish2000「prefering」には注意してくださいT const&const T&- @Justin時間が指摘するように、彼らはさまざまな種類があります。それは時には結果をもたらさないかもしれませんが、他の状況では、どちらかを好むように、どちらかを好むことが絶対に重要にintなりdoubleます。
omatai 2016年

3
@ fish2000-1つは「変更できないものに変更できる参照があります」と言い、もう1つは「変更できるものに変更できない参照があります」と言います。この例では、2つを交換することはできません。
omatai 2016

10

それを次のように変更します。

  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");

}

5

&s 文字列への一時的なポインタを生成し、一時的なオブジェクトを参照することはできません。


4
これは真実ではありません-constを一時的に参照できます
1800情報

3

試してください:

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

私がやっていることのために、私はポインターのアドレスと同様にポインター自体のアドレスが必要です。ポインタを値で渡したくありません。
アレックス、

それでもあなたが達成しようとしていることを理解していません。「string s」がポインタではないという理由だけで、「string s」の「ポインタのアドレス」を持つことはできません。
日本酒

@アレックス:文字列が内容が同じかどうかだけでなく、保存している別の文字列とまったく同じかどうかを検出する必要があると思います。その場合、参照にアドレス演算子を使用すると、参照されるオブジェクトのアドレスが取得されることに注意してください。void f(std :: string const&s){std :: string const * p =&s; }
デビッド・ロドリゲス- dribeas

3

編集:私はいくつかを試しました、そして、発見したものは私が思ったより少し微妙です。これが私が今正しいと思うことです。

&sは左辺値ではないため、参照のタイプがへの参照でない限り、それへの参照を作成できませんconst。たとえば、あなたはできません

string * &r = &s;

でもできる

string * const &r = &s;

関数ヘッダーに同様の宣言を配置すると、機能します。

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

別の問題、すなわち一時的な問題があります。ルールは、それがそうである場合にのみ、一時への参照を取得できるということですconst。したがって、この場合、&sは一時的なものでありconst、関数プロトタイプで宣言する必要があると主張するかもしれません。実用的な観点からは、この場合には違いはありません。(それは右辺値または一時値のいずれかです。どちらの方法でも同じルールが適用されます。)しかし、厳密に言えば、それは一時値ではなく右辺値だと思います。両者を区別する方法はあるのでしょうか。(おそらく、すべての一時値が右辺値であり、すべての非左辺値が一時値であると単純に定義されています。私は標準の専門家ではありません。)

そうは言っても、あなたの問題はおそらくより高いレベルにあります。のアドレスへの参照が必要なのはなぜsですか?へのポインタへの参照sが必要な場合は、次のようにポインタを定義する必要があります

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

への参照sまたはポインタが必要なs場合は、簡単なことを行います。


1

削除されたバイナリツリー内のすべてのポインターをルートセーフ以外にするために、ポインターへの参照を利用しました。ポインターを安全にするには、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)ポインターの場合、ポインターへの参照は無効です。


1

C ++ 11と右辺値参照へようこそ:

#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で、文字列のアドレスであるポインタ(によって参照される)の値にアクセスできます。

ポインタを変更することができ、誰も気にしません。これは、そもそも右辺値が何であるかの1つの側面です。

注意:ポインターの値は、myfunc()戻るまでのみ有効です。ついに、それは一時的なものです。


-1

ポインタの参照を渡すことは可能であることはわかっています。先週それを行いましたが、今のところあなたのコードは私の脳に正しく見えるので、構文が何であったか思い出せません。ただし、別のオプションは、ポインターのポインターを使用することです。

Myfunc(String** s)

-8

myfunc( "string *&val")これ自体は意味がありません。"string *&val"は "string val"、*を意味し、&はお互いをキャンセルします。最後に、文字列変数をfunction( "string val")に渡すことはできません。関数に渡すことができるのは基本データ型のみです。他のデータ型はポインターまたは参照として渡す必要があるためです。関数にはstring&valまたはstring * valのいずれかを指定できます。


4
すべてのレベルで間違っています。var宣言の構文を更新してください。
アリ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.