2009-07-14 31 views
9

std :: mapおよびstd :: hash_mapとは異なり、Qtの対応するバージョンでは参照を返すことはありません。非常に嵩張ったクラスのためにハッシュを構築すれば、それは非常に非効率的ではありませんか?その値によってそれを返す可能性が別のメソッド値が()があるので特にQHashとQMapがconst Tの代わりにconst Tを返す理由は何ですか?

EDIT

+0

[の可能な重複なぜ値でQMap ::演算子\ [\](constのキー&キー)リターンを行います?](https://stackoverflow.com/questions/18503700/why-does-qmapoperatorconst-key-key-return-by-value) –

+0

@ThomasKlier確かに、ちょうど5年前に尋ねた – MadH

答えて

29

STLコンテナの添字演算子は、コンテナに存在しないインデックスを使用してコンテナへの呼び出しをフラットアウトするため、reference-to-constを返すことができます。この場合の動作は未定義です。その結果、賢明な設計選択として、std::mapは、const添字演算子のオーバーロードを提供しない。

QMapは、より多くの文字を扱うために、constサブスクリプション演算子のオーバーロードを構文砂糖として提供し、存在しないキーを使用して問題に遭遇し、さらに調整を行い、代わりにデフォルト構成の値を返します。

STLの返り値参照規約を維持したい場合は、静的な値を割り当ててへの参照を返す必要があります。しかし、それはQMapが提供する再入荷保証とはかなり違っているので、唯一の選択肢は値で返すことです。 constconstmap["foo"]++のようないくつかの愚かな間違いを防ぐために糖衣を施すだけです。

つまり、参照渡しが常に効率的な方法であるとは限りません。基本型を返すか、より積極的な最適化を行った場合、sizeof(T)<=sizeof(void*)を返すと、コンパイラは結果をレジスタに直接渡します(レジスタへの結果へのアドレス指定)。スタック。

std::mapQMapの両方が値に基づいており、均質であるため、引用符で囲まれた参照を優先する別の理由(早すぎる苦味以外)は、ここでは適用されません。異機種のコンテナの場合は、ポインタを保持する必要があり、ポインタは基本的な型です(スマートなものを除く)。

これは、Qtでconst subscript演算子を使うことはほとんどありません。はい、それはfind() + *itよりも良い構文を持っていますが、必ず、count()/の直後にconstサブスクリプト演算子が呼び出されます。つまり、バイナリ検索を2回としています。そして、あなたはとにかく、戻り値のパフォーマンス:) value() constについては

で極小の違いを意識することはありませんそしては、しかし、私はそれを参照・ツー・デフォルト値をデフォルト、参照ツーのconstを返すべきであることに同意します2番目の引数として渡されていますが、Qtの開発者はそれがあまりにも多くの魔法を感じていたと思います。

+0

"std :: mapのconst添字演算子..."しかし、 'std :: map'には' const'添字演算子はありませんか? –

+0

十分に公正で、それを編集しました。しかし、細かいディテール: –

+0

"彼らはコンテナに存在しないインデックスを使って呼び出しを拒否しますが、これをstd :: mapで行うことができます。これは新しい値を挿入する方法の1つです。しかし、あなたが一般的な場合を意味していても、const subscript演算子を提供していないということはどのように続くのですか? – CiscoIPPhone

1

奇妙な、はい。おそらく、これは所望の意味論のためである。 value()は、指定されていないキーで、デフォルトで構成された適切な型の値を返します。参照を使用することは、少なくともきれいではありません。

また、name return value optimizationのようなものは、このデザインのパフォーマンスへの影響を軽減できます。

3

実際には、メソッドのいくつかは、例えば、operator[]の非constバージョンはT &を返す...リターンの参照を行います。

ただし、constバージョンoperator[]const Tを返します。どうして? 「解き放つ」が既に指摘しているように、その理由はキーが地図に存在しないときに何が起こるかと関係している。 non-const operator[]では、マップにキーを追加して、新しく追加されたエントリへの参照を返します。ただし、const operator[]はマップを変更できないため、これを行うことはできません。だから、それは何を参照する必要がありますか?解決策は、operator[]const Tの戻り値を返し、キーがマップに存在しない場合にはデフォルトの構成Tを返します。

+1

私は[これは、std ::とvalue()メソッドの値と同じものです。 – MadH

+0

しかし、なぜ 'const T QHash :: value(const Key&key、c​​onst T&defaultValue)const'は参照を返しません? –

4

特に、QMapとQHashのドキュメントでは、マーティンB氏が述べた理由のために、参照のためにoperator[]を検索しないようにしています。あなたはconst参照をしたい場合は、その後のいずれかを使用することができる場所

const_iterator find (const Key & key) constを使用します。

const Key & key() const 
const T & value() const 
const T & operator*() const 
const T * operator->() const 
関連する問題