7

ポインターのベクトル(または他のコンテナー)を反復処理する場合、以下を使用することの利点および/または利点に違いはありますか?

for (it = v.begin(); it != v.end(); ++it) {
    (*it)->method();
}

また

for (it = v.begin(); it != v.end(); ++it) {
    (**it).method();
}
4

5 に答える 5

10

C言語では、違いはありません。ただし、C ++では、->演算子はオーバーロードできますが、メンバー選択.演算子はオーバーロードできません。

したがって、inは、スマートポインターとして機能するクラスオブジェクトを指定できますが、がポインターの標準C ++コンテナーに対するイテレーターである(*foo)->bar *foo場合、これは発生しません。つまり、ポインターに評価されます。foo*foo

そして、(**foo).barでは、 (アクセス可能な)**fooというメンバーを持つクラスオブジェクトである必要barがあります。

単項演算*はオーバーロードすることもできます(これは、クラスオブジェクトであるイテレータがfoo参照するオブジェクトを返す方法です)。

言い換えると、式の意味は異なる可能性*fooがありますが、がクラス/構造体へのポインターである場合、C言語から継承された同等性が適用されます。(*ptr).memberは。と同等ptr->memberです。

于 2012-11-08T19:08:45.553 に答える
3

それらは同等です:標準で定義されているように(ポインタ用)

5.2.5クラスメンバーアクセス[expr.ref]
2:最初のオプション(ドット)の場合、最初の式は完全なクラスタイプでなければなりません。2番目のオプション(矢印)の場合、最初の式には完全なクラス型へのポインターが必要です。式E1->E2は、同等の形式(*(E1))。E2に変換されます。5.2.5の残りの部分は、最初のオプション(ドット)のみに対応します65。いずれの場合も、id-expressionは、クラスまたはその基本クラスの1つのメンバーを指定する必要があります。

コンテナにはポインタが含まれているため、クラスと->および*演算子のオーバーライドはここでは関係ありません。

したがって:

(*it)->method();

// Is equivelent to:

(*((*it))).method();

// This is equivelent too:

(**it).method(); // thus both expressions are identical in this context.
于 2012-11-08T19:35:52.080 に答える
2

いいえ->。構造体にポインタとしてアクセスするように指示するだけです。.単なる構造体のように機能します。それは相乗効果があります-機能の面で違いはありません。

編集:あなたは->それが同じことをしないと仮定しても、それが何か違うことをするようにオーバーロードすることができます。なぜそうするのかわかりませんが、そうする場合は、追加のを使用して構造体を再度逆参照する必要があります*

于 2012-11-08T19:08:17.380 に答える
0

それらは同じです。たとえば、使用するコーディング規則に応じて、どちらか一方を使用できます。

->演算子はオーバーロードできますが、*演算子はオーバーロード.できません。

于 2012-11-08T19:08:10.453 に答える
0

Ubuntu 12.04では、リストイテレータは次のように実装されています。

template<typename _Tp>
struct _List_iterator
{

  // ...
  reference
  operator*() const
  { return static_cast<_Node*>(_M_node)->_M_data; }

  pointer
  operator->() const
  { return std::__addressof(static_cast<_Node*>(_M_node)->_M_data); }

  // ...
于 2012-11-08T19:28:38.230 に答える