1

転送されたインプレース構築とは、std::allocator::constructとさまざまな emplace メソッド ( std::vector::emplace_back など) を意味します。C++ で転送されたインプレース構築では、リスト初期化構文を利用していない (できない?) ことがわかりました。その結果、集約をインプレースで構築することは決してできないようです。転送されたインプレース構築がリストの初期化をサポートしていないため、集計型がサポートされていないかどうかを確認したいだけです。これは言語の制限によるものですか?誰かがこの問題に関する標準への参照を提供できますか? 以下に図を示します。

直接のようにインプレース構築を行うことができますが、

int(*p)[3] = ...;
new(p) int[3]{1, 2, 3};

次のような転送されたインプレース構築はできません

std::allocator<int[3]> allo;
allo.construct(p, 1, 2, 3);
4

2 に答える 2

5

統一された初期化構文と呼ばれて{}きましたが、普遍的ではありません。

次の 2 つの例を見てください。

size_t a = 3;
size_t b = 1;
std::vector<size_t> v1{a,b};
std::vector<size_t> v2(a,b);

3最初のケースでは、2 つの要素とを含むベクトルを作成し1ます。

2 番目のケースでは、次を含むベクターを作成します1,1,1-- の 3 つのコピー1

実例

そのため、場合によっては、ベース コンストラクションがベース コンストラクション{}とは異なる動作を引き起こす可能性があり()ます。{}さらに、上記の場合、 (私が知っている) 構成を使用して「1 の 3 つのコピー」構文に到達する方法はありません。しかし、この{3,2}ケースは、イニシャライザ リストを明示的に作成して に渡すだけで処理できます()

初期化子リストを取るほとんどの型は、初期化子リストを明示的に渡すことによって emplace 構築でき、C++ 標準ライブラリは、コンストラクターを持たない型よりも多くのコンストラクターを持つ型用に設計されているため、C++ 標準ライブラリは、 and not を使用してほぼ均一に emplace 構造を使用(){}ます。

欠点は、リスト初期化が必要な型をこのメカニズムで配置できないことです。

理論的には、代わりにlist_emplaceusing を構築するメソッド{}を各インターフェイスに追加できます。それを提案することをお勧めします!

于 2015-04-10T16:17:54.060 に答える
3

std::allocatorconstruct()(および によって提供されるデフォルトの実装もstd::allocator_traits) を使用するように指定されています()( ::new((void *)p) U(std::forward<Args>(args)...)[allocator.members]/p12、[allocator.traits.members]/p5 を参照)。

{}この時点で変更するのは現実的ではありません。既存のコードが黙って壊れてしまうからです。

std::vector<std::vector<int>> foo;
foo.emplace_back(10, 10); // add a vector of ten 10s with (); two 10s with {}

動作しない場合に使用するようにフォールバックさせるLWG の問題があります。委員会がその方向性に同意するかどうかを確認する必要があります。{}()

@Yakk は、このアプローチの潜在的な欠点を指摘しています。

foo.emplace_back(10); // ten 0s
foo.emplace_back(10, 10); // ten 10s
foo.emplace_back(10, 10, 10); // three(!) 10s

同様の問題 ( N2215の付録 B を参照) により、リストの初期化では常にinitializer_listコンストラクターが優先されるという決定が下されました。

于 2015-04-10T16:20:37.230 に答える