古いalloctaor :: constructと新しいalloctaor :: constructの違いは何ですか?


15

私が知っているようにstd::allocator<T>::construct、C ++の古いバージョンでは2つのパラメーターしか使用しません。T1つ目は、型のオブジェクトを構築する生の未構築メモリへのポインタで、2つ目は、そのオブジェクトを初期化するための要素型の値です。したがって、コピーコンストラクタが呼び出されます。

struct Foo {
    Foo(int, int) { cout << "Foo(int, int)" << endl; }
    /*explicit*/ Foo(int) { cout << "Foo(int)" << endl; }
    Foo(const Foo&) { cout << "Foo(const Foo&)" << endl; }
};

int main(int argc, char* argv[]) {


    allocator<Foo> a;
    Foo* const p = a.allocate(200, NULL); // second parameter is required on C++98 but on C++11 it is optional
//  Foo* const p = a.allocate(200); // works fine on C++11 but not on C++98

    a.construct(p, 5, 7); // works on C++ 11 and up but not C++98
    a.construct(p, 10);// works on both
    a.destroy(p);
    a.destroy(p + 1);
    a.deallocate(p, 200);



    std::cout << std::endl;
}
  • C ++ 98ではa.construct(p, 10)コピーコンストラクターを呼び出すのに、C ++ 11以降では整数を受け取るコンストラクターだけを呼び出すのはなぜですか?

  • これはコンストラクタがあっても理由はいくつかのコピーエリジオンの最適化のC ++ 11の上に意味がFoo(int)あるexplicitように、コールの作品:a.construct(p, 5)でも、コンストラクタC ++ 11の作品がありexplicit、私は確信している場合、それはC ++ 98上で動作しませんですのよ何Foo(int)ですexplicit

  • もしそうなら、そのステートメントを何らかのcopy-elision最適化を無効にしてコンパイルすると、コンパイラは失敗しますか?ありがとうございました。


3
短い答え:C ++ 11までは、完璧な転送はありませんでした。詳細は@flyxが提供します。コピー省略は含まれていないことに注意してください(値渡しまたは値渡し)。
Daniel Langr

回答:


13

これはconstruct 、C ++ 11変更された宣言が原因です

void construct( pointer p, const_reference val );  (1)  (until C++11)
template< class U, class... Args >
void construct( U* p, Args&&... args );            (2)  (since C++11)

最初の宣言はコピーコンストラクターを呼び出し、2番目の宣言は指定された引数のリストに一致するコンストラクターを呼び出します。これはコピーコンストラクターの場合もありますが、コードで見た別のコンストラクターの場合もあります。

a.construct(p, 10)はコンストラクタ10Foo介して暗黙的に変換されるため、C ++ 98でコピーコンストラクタを呼び出しますFoo(int)。C ++ 11では、int(正確にはC ++ 98での変換に使用されたコンストラクター)をとる一致するコンストラクターがあるため、この変換は必要ありません。これはまた、あなたが追加したときにコードがC ++ 98で仕事をしない理由であるexplicit-それは変換できません10Foo、その後。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.