2013-05-03 9 views
24

私はstd::vectorの仕様を見ていて、reference typedefがC++ 11のAllocator::referenceからvalue_type&のC++ 11に変更されていることに気づいた。私はびっくりしたので、もっと深く見始めました。 CにおいてAllocator :: referenceを段階的に廃止するのはなぜですか?

++ 03§20.1.5[lib.allocator.requirements] X::referenceT&X::const_referenceT const&であると定義されることが定義されているテーブル32があります。

しかし、C++ 11§17.6.3.5[allocator.requirements]には、referenceconst_referenceが存在しないテーブル28があります。

次に、referenceを含まないC++ 11で追加された§20.6.8std::allocator_traitsがあります。しかし、§20.6.9std::allocatorはそうです。

最後にあります§23.2.1[container.requirements.general]「TのCONST左辺値」と「Tの左辺値」とX::const_referenceことがX::referenceを定義します。

だから、私はアロケータの要件からreferenceの除去を提案しているが、それはその背後にあるいずれかの根拠を言及していないことGoogleで検索し、この紙(12)を見つけました。しかし、変更に反対するLWG issueもあります。

また、私はその中で彼はreferenceは彼がコンテナ要素、コンテナの要件とstd::vector<bool>はコンテナではありませんどのようにポインタを取って話しているマシン固有のメモリレイアウトとHerb Sutter's postをカプセル化する方法を協議the interview with Alexander Stepanov発見しました。

だから、これについてどう思いますか? referenceは役に立ちましたか?その目的を果たしましたか?どのように "派手な"参照が標準に適合するのですか?これを完全に排除し、より厳格なコンテナ要件を満たし、std::vector<bool>を非難する大胆な動きですか?

+6

すてきな質問 – David

+0

いいえ、あまり太字ではありません。誰かがstd :: vectorをインスタンス化しようとするとビルドが中断します。

答えて

1

the interview with Alexander Stepanovで、スタンダードライブラリにSTLを追加する提案中に、彼はメモリモデルから抽象化を作成するよう求められたと述べる。こうしてアロケータが生まれました。 LWG issueでは、カスタムアロケータのreferenceT __far&と定義されている実装の例があります。

しかし、私は多くの時間を検索することはありませんので、未知の理由のために、C++ 03標準ではあり§20.1.5P4に次のテキスト:この中で説明した容器の

実装国際標準は、それらのアロケータテンプレートパラメータが表32のそれを超える以下の2つの追加要件を満たすと想定することが認められている。

- 指定されたアロケータタイプのすべてのインスタンスは互換性があり、常に互いに と等しいと比較する必要があります。

- typedefメンバポインタ、const_pointer、size_type、およびdifference_typeは、それぞれT *、T const *、size_t、およびptrdiff_tである必要があります です。

これは、カスタムメモリモデルアロケータの標準コンテナとの相互運用性を効果的に無効にします。

"allocator"という言葉が書かれているすべてのC++ 11以前の論文を検索している間、私はこれらの単語を標準から削除するという主要なコンセンサスを見つけました。最後に、this paperは、次の解説でそれらを削除することを提案しています。

ワッセルの言葉はなくなりました。あなたのガラスを上げ、トーストを作ってください。

Victory?ようやく私たちの記憶モデルで野生に行くことができますか?それほど多くはありません。とりわけ、同じ文書では、アロケータ要件からreferenceを削除することを提案しています。標準に投票されたようです。私は前に述べたLWG issue

は変更に反対したが、それは、次の文で閉じられました:ない

コンセンサスが

だから、それはアロケータの本来の目的のように見える変更を行います今日はとても重要です。

アロケータの現在の目的は、基礎となるハードウェアのアドレスモデルを適応させるのではなく、コンテナ内のメモリ割り当てをプログラマに制御させることです。実際には、改訂された標準では、アロケータがC++アドレスモデルへの拡張を表現し、正式に(意図的に)それらの本来の目的を排除する能力がなくなりました。

最後に、Container::referenceはアロケータとは関係ありません。これはプロキシされたコレクションwhich are not actually containersを許可するために作成されました。それで、ここに滞在します。ところで、それは、スタンダードの最終的な言葉が元の意図とはどのように逆行するかの別の例のようです。

+1

「理由が不明」のウィキペディアページの第2段落に記載されています... –

4

ネストされたtypedefは余分なものであるためです。 スコットマイヤーズ有効STL、ページ49:

規格が明示的にライブラリ実装が すべてのアロケータのポインタのtypedefがT *の同義語であり、すべての アロケータの参照のtypedefがT &

と同じであると仮定することができます
+0

私が実際にリンクした論文は、これを標準から削除することを提案しています。 – Lyberta

+0

それは壊れやすい変化である可能性があるので、おそらく遅く、ベクトルなどからの参照を巻き戻しているでしょう。それでも、私は標準からのすべてのあいまいさを取り除くことに賛成です。 –

2

http://en.wikipedia.org/wiki/Allocator_(C%2B%2B)

「彼らはもともとプログラマがライブラリでカスタムポインタと参照型を利用することができ、ライブラリーをより柔軟かつ根本的なメモリモデルに依存しないようにする手段として意図されていた。しかし、中にC++標準にSTLを採用する過程で、C++標準化委員会は、メモリモデルを完全に抽象化すると、許容できないパフォーマンスの低下を招くことに気付きました。これを解決するために、アロケータの要件が制限されました。アロケータによるものは、もともとStepanovによって計画されていたよりも限られている。「

はもともと彼らは、接続を介して、インターネット、1が言うにメモリを割り当てることができ、離れた抽象に別のマシンをメモリ自体をデザインした、ライブ何を追跡するために、ポインタ/参照を使用して、前後のデータをコピーします同じように、純粋なC++でJavaのようなGCを作ることができます。この抽象化は素晴らしいアイデアのように思えます!

しかし、これは当時は受け入れられないパフォーマンスペナルティを招いていました。コードで作業するのはほとんど不可能です。void func(const string&)はすべてtemplate<class allocator> void func(allocator::reference)にする必要があります。これは非重力のコンテキストなので、明示的に関数呼び出し(func<std::allocator<std::string>::const_reference>(username))にアロケータを書き込んでください。これは誰も実行しないので、GCが正しく動作しなくなります。今日、アロケータは単にメモリ割り当て/解放を抽象化するだけです。

関連する問題