2017-02-13 15 views
3

STLにはイテレータを返す多くの関数があります。たとえば、STLリスト関数eraseは、イテレータ(C++ 98とC++ 11の両方)を返します。それにもかかわらず、私はそれがvoid関数として使われているのを見ています。C++ STL - イテレータをvoid関数として返す関数を扱うのはなぜですか?

mylist.erase(it1, it2); 

反復子を返しません。でも、cplusplus.comサイトでは、次のコードが含まれている例があります。適切な構文は次のようにすべきではありませんか?イテレータを返しません

std::list<int>::iterator iterList = mylist.erase(it1, it2)? 
+1

戻り値の型を気にしない場合、なぜそれを格納しますか? – user975989

+3

あなたはそれを使用するつもりがない場合は、いつでも返品を無視することができます。また最近では 'auto'を使用しています:) –

+0

すべての教授が学生に" auto "を使用できるわけではありません。彼らは私たちがどのようにタイプを理解しているかを私たちにテストする必要があります。 –

答えて

7

。適切な構文は、 のようにしてはいけませんか?

イテレータは返されますが、他の関数と同様に、返された値は無視できます。要素を消去し、返されるイテレータを気にしない場合は、単純に無視してもかまいません。

戻り値を実際に無視するのは、予想以上に一般的です。戻り値が無視される最も一般的な場所は、戻り値の唯一の目的が連鎖を有効にすることである場合があります。たとえば、代入演算子は通常、a = b = cのように書くことができるように、

Foo& operator=(const Foo& other){ 
    /*...*/ 
    return *this; 
} 

と書かれています。ただし、b = cと書いた場合、通常はその呼び出しによって返された値は無視されます。また、b = cと書くと、これは値を返しますが、この割り当てをしたいだけなら、戻り値を無視する以外の方法はありません。

8

C++では、戻り値を使用する必要はありません。通常、返されるイテレータは、そのコンテナに対して新しい有効なイテレータを持つのに便利です。しかし、構文的には正しいです。消去後、it1it2はもう有効ではないことにご注意ください。

+1

実際には、 'std :: list'はある特定のコンテナに対しては特別ですが、' it2'は有効なままです。 –

+0

ありがとうございました。 – Praise

+0

C++では、文法上正しいものではないさまざまなことを実行できます。プログラムが実行されていれば、コードが正しいことを意味するわけではありません。ルールは、関数が値を返すと宣言されている場合、**は値を返す必要があるということです。したがって、関数が値を返すことを無視することは良い選択のようには見えません。おそらくSTLに関連した、より正当な理由があると私は考えました。 –

1

実際の理由はあなたが考えるよりははるかに辛いです。戻り値を無視できない場合、.erase()のような関数の多くは、.erase()のバージョンがvoidを返し、もう1つが.erase_and_return()のイテレータを返すという2つのバージョンに分割する必要があります。あなたはこれから何を得るでしょうか?

+0

さて、私の友人には、['std :: ignore'](http://en.cppreference.com/w/cpp/utility/tuple/ignore)、または一般的にそのようなものがあります。しかし、それは非常に冗長です。 –

1

戻り値は時には有用な場合もあります。有用でない場合は、それらを使用する必要はありません。

すべてcontainer.erase関数は、新たに消去された範囲の後にイテレータを返します。非ノードベースのコンテナの場合、範囲内のイテレータとその後のイテレータはもはや有効ではないため、これは(必ずしもそうではありませんが)しばしば役に立ちます。

ノードベースのコンテナの場合、2番目のイテレータが渡されると、消去操作後でも有効なままなので、これは通常役に立たなくなります。

いずれにせよ、どちらもイテレータを返します。これにより、ジェネリックコンテナで動作するコードは、コンテナが消去後に有効なイテレータを保持しているかどうかを知る必要がなくなります。それは単に戻り値を格納し、後で消去するための有効なイテレータを持つことができます。

C++標準コンテナのイテレータは、作成、破棄、コピーするのに非常に安価です。実際には、コンパイラが使用されていなければ完全に削除することができるので、実際には安価です。したがって、使用されていないイテレータを返すと、実行時コストはゼロになります。

ここでこの戻り値を使用しないプログラムは、意味的および構文的に正しいプログラムにすることができます。同時に、他の意味的および構文的に正しいプログラムでは、その戻り値を使用する必要があります。最後に

mylist.erase(it1, it2); 

これはイテレータを返すん。イテレータは直ちに破棄されます(戻り値は名前のない一時的なものとしてのみ存在します)。また、コンパイラはその値を最適化する可能性があります。

しかし、戻り値を格納していないからといって、返されないというわけではありません。

関連する問題