web-dev-qa-db-ja.com

size()とベクトルのempty()-なぜempty()が好まれるのですか?

何かをデバッグしているときに、STL vector :: empty()の実装を見ました:

bool empty() const
        {return (size() == 0); }

ベクトルの空を調べるときは常に、size()よりも空を使用することをお勧めします。しかし、その実装を見て、私は疑問に思っています、そうすることの利点は何ですか?代わりに、内部でsize()== 0を呼び出すため、emptyの呼び出しには関数呼び出しのオーバーヘッドがあります。

Size()はリスト内の定数時間を保証しないため、リストの場合はempty()が役立つと思いました。私の仮定を検証するために、リストの実装を確認しましたが、驚くべきことに、リストにも同じ実装が見つかりました。

return (size() == 0);

私は今少し混乱しています。 emptyが内部でsize()を使用している場合、size()よりもemptyを優先する必要があるのはなぜですか?

32
aJ.

size()を使用するたびに条件を書き出す必要があります。 empty()を使用すると便利です。もちろん、これはコンテナを切り替えない限りです。他の人が指摘しているように、size()empty()を使用するかどうかは実装次第です。ただし、この標準では、次のことが保証されています。empty()はすべての標準コンテナの定数時間操作です。

26
dirkgently

Std :: vectorからstd :: listまたは他のコンテナに切り替えると、異なる場合があるためです。

たとえば、_std::list::size_の一部の実装は、O(n)ではなくO(1)を取ります。

43
Artyom

さて、あなたが言うように、それは単なる実装の詳細です。 _std::list_は、保存されたサイズ(constant-time size() but linear-time splice())またはなし(constant-time splice())のいずれかで実装できます。しかし、線形時間size())。 empty()を使用することを選択することにより、サイズを知る必要がないときに、実装の詳細に賭けることを回避できます。

10

標準に従って、empty()は、コンテナーのタイプに関係なく一定の時間計算量を持つため、優先する必要があります。

C++ 03標準、第23.1章、表65:コンテナ要件

Operation:   empty()
Return_type: convertible to bool
Semantics:   equivalent to size()==0
Complexity:  constant

STL実装では、複雑さの要件を無視して実際の実装としてセマンティクスを採用したようです。または、size()は実装(格納フィールド)で一定時間です。

Size()が一定の時間でない場合は、std :: list <> :: empty()が標準のコンテナ要件を満たしていないことについてベンダーに問い合わせてください。

まず、何かが空かどうかを知りたいときにempty()という関数を使用すると、コードが読みやすくなり、実装の詳細について心配する必要がなくなります。また、他の特性を備えた他のタイプのコンテナーにコードをより簡単に適合させることができることも意味します。

2つ目は、これは1つのSTL実装にすぎません。私のGNU C++は次のようになります:

_bool
empty() const
{ return begin() == end(); }
_

これにより、最終的にはポインターの比較が行われ、size()を使用すると減算が行われます(この実装では)。

第3に、empty()-関数はおそらくインライン化されているため(両方の実装で)、余分な関数呼び出しのオーバーヘッドが発生する可能性はほとんどありません。

5
gnud

empty()にはすべてのコンテナクラスのO(1)実装があります。size()は一部のコンテナのO(n)実装のみを提供できます。これが理由です。 empty()が推奨されます。

4
paxos1977

上記の理由に加えて、foo.size()== 0および/または!foo.size()よりも間違いなく明確です。

1
Alex

非常に有効な読みやすさの点に加えて、あなたが経験したのは、唯一の可能な実装ではなく、特定の実装の成果物にすぎません。

つまり、vectorとlistの両方のケースで、または他のコンテナで、size()の観点からempty()を実装する理由や要件はありません。より良いパフォーマンスの代替案がある場合は、ライブラリの作成者が無能であるか、より合理的に怠惰でない限り、それらを使用する必要があります。

リストとsize()のO(1)性、またはその欠如については、リストがsize()をO(1)またはsplice()ですが、両方ではありません(理由を考えるのは興味深い演習です)。したがって、あなたの場合、検査したライブラリはsize()をO(1)( case splice()はO(n))であるため、パフォーマンスを犠牲にすることなくsize()に関してempty()を実装できます。そうしないと、ライブラリが非常に悪くなります。

0
Ash

各コンテナは、定数時間操作を取得するために異なる方法でempty()実装を実装する可能性があるため、size()よりもempty()を使用することをお勧めします。

例:

vectorは次のように実装します:bool empty()const {//シーケンスが空かどうかをテストしますreturn(size()== 0); }

リストは次のように実装されます:

        bool empty() const
    {   // test if sequence is empty
    return (_Mysize == 0);
    }
0
Jakkula Vamsi