2011-08-04 6 views
2

対呼び出す:C++ネストされたコンストラクタは、関数の宣言次のコードセクションの「バージョン1」と「バージョン2」と表示されたコードスニペットとの違いは何ですか

int main() { 
    using namespace std; 
    typedef istream_iterator<int> input; 

    // version 1) 
    //vector<int> v(input(cin), input()); 

    // version 2) 
    input endofinput; 
    vector<int> v(input(cin), endofinput); 
} 

私の知る限り理解し、「バージョン1 "は関数宣言として扱われます。しかし、私はなぜ返り値がvector<int>の関数vの引数が何であるのか理解できません。

答えて

4

なぜ

標準は、おそらく関数の宣言と解釈することができるものは何で、どの文脈で、あることないこと、多かれ少なかれ、と言うので。

は、引数が...

何であるかをあなたはこれを信じていないかもしれませんが、それは本当です。 input(cin)input cinと扱われます。この場所では、かっこが許されていて、単に無意味です。ただし、input()は、名前のない型inputのパラメータを宣言するものとして扱われません。その代わりに、タイプinput(*)()のパラメータ、つまり引数を取らずにinputを返す関数へのポインタです。その型を宣言する際には、(*)部分は不要です。私は、関数ポインタを初期化するために関数名を使用するときに&がオプションであるのと同じ理由を推測します...

istream_iterator<int> start(cin), end; 
vector<int> v(start, end); 

もう一つの方法は「にISN方法で括弧を追加することです:

もう一つの方法は、私たちがtypedefのをスキップ正当化するために、別途とにかく値を宣言しているという事実を利用して、この問題を回避するには関数宣言には許可されていません。

vector<int> v((input(cin)), input()); 

詳細については、Googleの "C++ most vexing parse"を参照してください。

+0

入力イテレータがForwardIteratorsではなく、それらを反復処理するためイテレータが使用されないため、イテレータが残っていないため、後で使用することをお勧めします。 –

+0

あなたがたどり着かないことが必要な場合は、いつも別のスコープを作成することができます:)私は誤って無効なイテレータを使用するリスクは低いと考えています。なぜあなたは誘惑されますか? –

+0

これは、何か間違ったことが起こる恐れよりも味の問題です。彼らは周りにいる必要はありませんし、彼らは名前を付ける必要はないので、私は彼らがそうでないことを好む。 –

1
vector<int> v(input(cin), input()); 

さて、この関数宣言の引数は、これらは以下のとおりです。

  • input(cin)からinputを戻し、引数を取らない関数へのポインタです - オブジェクト
  • input (*)()です。
2

これはmost vexing parseと呼ばれる:

このコード:

input() 

は、クラスの匿名のインスタンスを取って、どちらか

  1. 変数クラスの入力のための変数定義として明確化することができ入力または
  2. afの関数宣言型入力のオブジェクトを返すunctionは、型入力を返す関数(および入力を受けない)である単一の(名前のない)引数をとります。

ほとんどのプログラマは最初のものを期待していますが、C++標準では2番目のものと解釈する必要があります。

関連する問題