3
#include <memory>

struct foo
{
    std::unique_ptr<int> p;
};

int main()
{
    foo bar { std::unique_ptr<int>(new int(42)) };
    // okay

    new foo { std::unique_ptr<int>(new int(42)) };
    // error: no matching function for call to
    // 'foo::foo(<brace-enclosed initializer list>)'
}

一様な初期化は動的オブジェクトでは機能しませんか、それとも g++ 4.6.1 の欠点ですか?


g++ 4.7.1 で動作しますが、別のクラスから継承する場合、両方の行mainがコンパイルに失敗します。foo

struct baz
{
    // no data members, just some member functions
};

struct foo : baz
{
    std::unique_ptr<int> p;
};

繰り返しますが、私のコンパイラの欠点ですか? それとも、均一な初期化は継承でうまく機能しませんか?

4

3 に答える 3

4

g++-4.7 で問題なくビルドできます。したがって、おそらく後者です。ドキュメントを介してより強力な証拠を見つけることができるかどうかを確認します.

そして、継承補遺への対応として:

この単純なケースもコンパイルに失敗します。

struct baz
{
};

struct foo : baz
{
    int b;
};

int main()
{
    foo bar { 12 };
}

と:

testoo.cpp:14:18: error: no matching function for call to ‘foo::foo(<brace-enclosed initializer list>)’
testoo.cpp:14:18: note: candidates are:
testoo.cpp:7:8: note: foo::foo()
testoo.cpp:7:8: note:   candidate expects 0 arguments, 1 provided
testoo.cpp:7:8: note: constexpr foo::foo(const foo&)
testoo.cpp:7:8: note:   no known conversion for argument 1 from ‘int’ to ‘const foo&’
testoo.cpp:7:8: note: constexpr foo::foo(foo&&)
testoo.cpp:7:8: note:   no known conversion for argument 1 from ‘int’ to ‘foo&&’

標準の私の読書によると、あなたはaggregate initializationあなたの最初の例に入っています:

集合体は、ユーザー提供のコンストラクター (12.1)、非静的データ メンバーのブレースまたはイコール初期化子 (9.2)、プライベートまたは保護された非静的データ メンバー (条項 11)、基本クラスなし (条項 10)、および仮想関数なし (10.3)。

8.5.4 で指定されているように、初期化子リストによって集合体が初期化されると、初期化子リストの要素は、添え字またはメンバーの昇順で、集合体のメンバーの初期化子として取得されます。

これは基本クラスを明示的に禁止することに注意してください。要約すると、基本クラスが存在する場合、集約の初期化は許可されません。したがって、2 番目の例はどちらもコンパイルされません。

于 2012-07-09T12:23:44.103 に答える
2

別のクラスから継承する場合、両方の行mainがコンパイルに失敗しますfoo

ああ、一様な初期化は、集約と非集約で異なる働きをします:

型 T のオブジェクトまたは参照のリスト初期化は、次のように定義されます。

  • T が集合体の場合、集合体の初期化が実行されます
  • [...]
  • それ以外の場合、T がクラス型の場合、コンストラクターが考慮されます

集約は [..] クラス [...] であり、基本クラス [...] も仮想関数もありません。

したがって、ここではサブタイプのポリモーフィズムが必要なので、私の場合はカスタム コンストラクターを作成する必要があります。

于 2012-07-09T13:30:53.363 に答える
1

現在、最終バージョンは手元にありませんが、ドラフトN3242に§ 8.5.4 List-initializationは、リストの初期化を新しい式の初期化子として使用できることが明示的に記載されています。また、次の例も提供します。

new std::vector<std::string>{"once", "upon", "a", "time"}; // 4 string elements
于 2012-07-09T13:10:41.100 に答える