ポインターのベクトル(または他のコンテナー)を反復処理する場合、以下を使用することの利点および/または利点に違いはありますか?
for (it = v.begin(); it != v.end(); ++it) {
(*it)->method();
}
また
for (it = v.begin(); it != v.end(); ++it) {
(**it).method();
}
ポインターのベクトル(または他のコンテナー)を反復処理する場合、以下を使用することの利点および/または利点に違いはありますか?
for (it = v.begin(); it != v.end(); ++it) {
(*it)->method();
}
また
for (it = v.begin(); it != v.end(); ++it) {
(**it).method();
}
C言語では、違いはありません。ただし、C ++では、->
演算子はオーバーロードできますが、メンバー選択.
演算子はオーバーロードできません。
したがって、inは、スマートポインターとして機能するクラスオブジェクトを指定できますが、がポインターの標準C ++コンテナーに対するイテレーターである(*foo)->bar
*foo
場合、これは発生しません。つまり、ポインターに評価されます。foo
*foo
そして、(**foo).bar
では、 (アクセス可能な)**foo
というメンバーを持つクラスオブジェクトである必要bar
があります。
単項演算*
はオーバーロードすることもできます(これは、クラスオブジェクトであるイテレータがfoo
参照するオブジェクトを返す方法です)。
言い換えると、式の意味は異なる可能性*foo
がありますが、がクラス/構造体へのポインターである場合、C言語から継承された同等性が適用されます。(*ptr).member
は。と同等ptr->member
です。
それらは同等です:標準で定義されているように(ポインタ用)
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.
いいえ->
。構造体にポインタとしてアクセスするように指示するだけです。.
単なる構造体のように機能します。それは相乗効果があります-機能の面で違いはありません。
編集:あなたは->
それが同じことをしないと仮定しても、それが何か違うことをするようにオーバーロードすることができます。なぜそうするのかわかりませんが、そうする場合は、追加のを使用して構造体を再度逆参照する必要があります*
。
それらは同じです。たとえば、使用するコーディング規則に応じて、どちらか一方を使用できます。
->
演算子はオーバーロードできますが、*
演算子はオーバーロード.
できません。
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); }
// ...