2016-10-20 8 views
2
#include <vector> 
#include <queue> 
using namespace std; 
int main() 
{ 
    vector<priority_queue<int>> vec; 
    vec.push_back({});//compiles 
    vec.push_back({1});//don't work 
    vec[0] = {};//compiles 
    vec[0] = {1};//don't work 
    return 0; 
} 

priority_queueには初期化子リストコンストラクタがありません。既に存在するオブジェクトに{}を割り当てるとはどういう意味ですか?

でも、まだ{}を割り当てることができます。

私は、デフォルトのコンストラクタを使用して空のpriority_queueを作成し、それを既に存在するpriority_queueオブジェクトに割り当てたことを意味すると思います。

しかし、このようなものではありませんか?

これはどういう意味ですか、それはなぜ機能しますか? priority_queue部分を省略しました。

vec[0] = {};//compiles 
vec[0] =();//don't work 

私のキューオブジェクトをいつでも再初期化できますか?

priority_queue<int> que{}; 
que = {};//compiles 
que{};//don't work 

ここではnullptrのようなものがありますか?

{}は、nullptrがすべての種類のポインタのための空のポインタのようなものすべてのための空のオブジェクトですか?

priority_queue<int>* p{}; 
p = nullptr; 
p = {};// still works 
+3

旧C++は何かを初期化するためのさまざまな方法の多くを持っていました。そこで、新しい*ユニフォーム初期化*を追加しました。今ではすべての古い方法と別の新しい方法があります。 –

+0

'priority_queue'のデフォルトのコンストラクタが'明示的に '起こるので、これは実際には不正です。おそらくスタンダードの欠陥でしょう。 –

+0

新しい方法では、古い方法よりもコーナーケースがさらに多くなります。 –

答えて

4

代入演算子(複合代入を含む)は、リスト初期化が許可されているコンテキストのリストに含まれているので、C++ 11では特別な扱いが与えられています。その特別な治療のので平野{ ... }初期化子が代入演算子の仕様に応じて、そして、あなたの

vec[0] = {}; 

のように、代入演算子の右側に許可され、それが

vec[0].operator =({}); 
として解釈されます

この場合、{}は、関数呼び出しの引数の初期化子として使用されます。初期化されるオブジェクトは集合体ではないため、{}の内容は通常のコンストラクタの引数リストとして解釈されます。リストは空であるため、デフォルトコンストラクタが選択されます。

この特別な治療法は、他の事業者には拡張されません

struct S 
{ 
    S(int, int, int) {} 
    S &operator +=(const S& rhs) { return *this; } 
    S operator +(const S& rhs) const { return *this; } 
}; 

int main() 
{ 
    S s(1, 2, 3); 
    s = { 4, 5, 6 }; // OK - special treatment for `=` 
    s += { 4, 5, 6 }; // OK - special treatment for `+=` 
    s + { 4, 5, 6 }; // Error - no special treatment for `+` 
    s + S{ 4, 5, 6 }; // OK, constructing the object explicitly works 
} 
+0

ここで落とし穴に言及しておきましょう: 'operator ='のオーバーロードが複数ある場合、オーバーロードの解決は驚くべき結果をもたらすかもしれません( '{} 'の組み込み型への変換がクラス型への変換よりも優先されるので、選択することはできません)。 –

+1

@MM: '{1}'のような初期化子が組み込みの型を好むかもしれないという事実はかなり自然なように見えるかもしれませんが、 '{}'も組み込みの型を好むという事実は多くの人にとって驚くかもしれません。 – AnT

2

中括弧({})は、オブジェクトだけでなく、初期化子リストの初期化のために一般的に使用されています。したがって、初期化子リストを持たないクラスは、オブジェクトを初期化するためにカッコを使用することができます。

class A { 
    public: 
    A(int i); 
} 

A a{5}; // Invokes A's constructor 

はまたaggregate initializationのために使用することができる(構造体データメンバの例えば初期化。)あなたのケースでは、それはpriority_queueの既定のコンストラクタを呼び出しています。

関連する問題