11

重複の可能性:
演算子のオーバーロード ->

やあ、

評価後に連鎖(再適用)されるのを見てきました。operator->()たとえば、次のようになります。

struct Bar
{
  Bar() : m_str("Hello world!") {}
  const string* operator->() const { return &m_str; }
  string m_str;
};

struct Foo
{
  const Bar& operator->() const { return m_bar; }
  Bar m_bar;
};

int main()
{
  Foo f;
  cout << f->c_str() << endl;
  return 0;
}

これには、3 つを評価する必要がありoperator->()ます - Foo::operator->()Bar::operator->()および通常のポインター解決。

ただし、途中でポインターを使用すると機能しFoo::operator->()ません。参照ではなくバーへのポインターを返すと、コンパイルされません。auto_ptr<auto_ptr<string>> たとえば、同じことが起こります。

非過負荷に固有なoperator->()ので、一度だけ適用され、連鎖は発生しませんか? を使用せずに以下のコードを動作させることは可能(*ptr2)-> ...ですか?

int main()
{
  string s = "Hello world";
  auto_ptr<string> ptr1(&s);
  auto_ptr<auto_ptr<string> > ptr2(&ptr1);
  cout << ptr1->c_str() << endl; // fine
  cout << ptr2->c_str() << endl; // breaks compilation
}

ありがとう!

4

3 に答える 3

22

C++98 標準 §13.5.6/1「クラス メンバー アクセス」:

存在する場合、およびオーバーロード解決メカニズム (13.3) によって最適一致関数で演算子が選択された場合、式は型のクラス オブジェクトx->mとして解釈されます。(x.operator->())->mxTT::operator->

これが実際に意味することxは、 がポインターの場合、連鎖しないということです。次に、組み込みを取得しますoperator->(つまりx->mxポインターを使用すると に変換されます(*x).m)。

しかし、xがクラス type のオブジェクトである場合T、連鎖効果が得られます。その場合、それ自体が何らかのクラスのオブジェクトであると解釈(x.operator->())->mできるため(x.operator->())、たとえば classUです。2 番目->は として解決できU::operator->、その結果が再びクラス型オブジェクトである場合…

同様に、あなたの場合、を定義するFoo::operator->class のオブジェクト (への参照) を生成します。Baroperator->

しかし、operator->たとえばポインタを返す場合、使用されるのstd::auto_ptr<T>::operator->はビルトインだけoperator->です。

ちなみに、チェーン使用して、誰かがdelete不適切に使用するのを実質的に防ぐことができます。std::auto_ptrそれはしません。そして、私はそれが行われたのを見たことがありません。

deleteしかし、[comp.lang.c++.moderated]で、スマート ポインターによって管理される未加工のポインターの不注意を防ぐ方法について、長い議論のスレッドがありました。これは、議論された 1 つの可能性でした。

乾杯 & hth。

于 2011-02-07T16:23:05.760 に答える
3

最初の例が機能する理由は、ポインターではなく参照を返したためです。その演算子は、オーバーロードされている場合を除いて、通常は無効です。したがって、コンパイラはオーバーロードされた関数をチェーンの下流で実行する必要があります。ただし、auto_ptr実際には実際のポインタが返さoperator ->れ、通常のポインタに対してデフォルトが呼び出されます。

詳細については、オーバーロード演算子->質問を参照してください。

于 2011-02-07T15:53:34.160 に答える
0

いいえ、動作しません。あなたが過負荷operator ->になることができればstring *、それを機能させることができます。しかし、operator ->すでにすべてのポインタタイプの定義があります。したがって、+プリミティブ数値タイプに対してオーバーロードできないのと同様operator ->に、ポインタータイプに対してオーバーロードすることはできません。

そして、可能であったとしても、コンパイラは再帰がいつ終了するかをどのように知ることができますか?

于 2011-02-07T15:51:45.950 に答える