web-dev-qa-db-ja.com

C ++でのポインターへの参照の受け渡し

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

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

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

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

そして、私はこのエラーを受け取っています:

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

120
Alex

関数は、匿名の文字列ポインターではなく、呼び出しスコープ内の実際の文字列ポインターへの参照を想定しています。副<文>この[前述の事実の]結果として、それ故に、従って、だから◆【同】consequently; therefore <文>このような方法で、このようにして、こんなふうに、上に述べたように◆【同】in this manner <文>そのような程度まで<文> AひいてはB◆【用法】A and thus B <文>例えば◆【同】for example; as an example:

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

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

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

118
Chris

問題は、参照に一時をバインドしようとしていることです。参照がconstでない限り、C++では許可されません。

したがって、次のいずれかを実行できます。

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;
}
84
Michael Burr

次のように変更します。

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

}
10
aJ.

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

5
n0rd

試してください:

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

編集:私はいくつかを実験しましたが、発見したことは思ったよりも少し微妙です。これが正確な答えだと思うものです。

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

string * &r = &s;

でもできる

string * const &r = &s;

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

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

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

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

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

sへの参照またはsへのポインターが必要な場合は、簡単なことをしてください。

2
Ari

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

1
Mohd

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で参照)にアクセスできます。これは、文字列のアドレスです。

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

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

0
not-a-user