Подтвердить что ты не робот

Size() Vs empty() в векторе - почему пустым() является предпочтительным?

При отладке чего-то я увидел реализацию STL vector:: empty():

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

Я считаю, что всякий раз, когда мы исследуем пустоту вектора, всегда рекомендуется использовать пустой над size(). Но, видя эту реализацию, я задаюсь вопросом, в чем преимущество этого? Вместо этого есть накладные расходы на вызов функции при вызове пустого, поскольку он внутренне вызывает size() == 0.

Я думал, что empty() может оказаться полезным в случае списка, поскольку size() не гарантирует постоянное время в списке. Чтобы проверить мое предположение, я проверил реализацию списка и, что удивительно, нашел ту же реализацию в списке,

return (size() == 0);

Я немного запутался. Если пустым внутренне используется size(), то почему мы предпочитаем пустую над size()?

4b9b3361

Ответ 1

Вам нужно будет написать условие каждый раз, когда вы используете size(). Удобно использовать empty(). Это, конечно, при условии, что вы не переключаете контейнеры. Как указывали другие, до внедрения использовать size() в empty() или нет. Однако стандарт гарантирует, что: empty() - операция постоянной времени для всех стандартные контейнеры.

Ответ 2

Потому что если вы перейдете из std::vector в std:: list или другой контейнер, это может быть другим.

Например, некоторые реализации std::list::size принимают O(n), а не O(1).

Ответ 3

Ну, как вы говорите, это просто деталь реализации. std::list может быть реализован либо с сохраненным размером (постоянным временем size(), но с линейным временем splice()), либо без (постоянное время splice(), но линейное время size())). Выбирая использовать empty(), вы избегаете делать ставки на детали реализации, когда вам не нужно знать размер.

Ответ 4

Следуя стандарту, пустая() должна быть предпочтительной, так как она имеет постоянную временную сложность независимо от типа контейнера.

В стандарте С++ 03, глава 23.1, таблица 65: Требования к контейнеру

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

Кажется, что в вашей реализации STL они воспринимали семантику как реальную реализацию, игнорируя требования сложности, или size() - постоянное время в реализации (сохраненное поле).

Если size() не является постоянным временем, обратитесь к поставщику по адресу std:: list < > :: empty(), не выполнив стандартные требования к контейнеру.

Ответ 5

1st, используя функцию с именем empty(), когда вы хотите знать, что что-то пусто, делает код более читаемым и означает, что вам не нужно беспокоиться о деталях реализации. Это также означает, что ваш код легче адаптировать к другим типам контейнеров с другими характеристиками.

2nd, это только одна реализация STL. Мой GNU С++ выглядит так:

bool
empty() const
{ return begin() == end(); }

Это в конечном итоге приведет к сопоставлению указателей, в то время как использование size() приведет к вычитанию (в этой реализации).

В-третьих, это вряд ли приведет к накладным расходам дополнительного вызова функции, поскольку empty() -функция, вероятно, включена (в обеих реализациях).

Ответ 6

empty() имеет O (1) реализации для ВСЕХ контейнерных классов. size() может предоставлять только O (n) реализации для некоторых контейнеров; поэтому пустая() является предпочтительной.

Ответ 7

В дополнение к причинам, приведенным выше, это также возможно более ясное, чем foo.size() == 0 и/или! foo.size()

Ответ 8

Помимо точки удобочитаемости, которая является очень достоверной, то, что вы испытали, - это просто артефакты одной конкретной реализации, а не единственно возможная.

То есть, нет никаких оснований или требований, чтобы empty() реализовывался в терминах size() как в случае вектора, так и в списке, или в деле любого другого контейнера. Если есть более эффективные альтернативы, они должны использоваться, если автор библиотеки не являются некомпетентными или более разумно ленивыми.

Что касается списка и O (1) -ness size() или его отсутствия, вы должны учитывать, что этот список может реализовать либо size(), либо O (1), либо splice(), но не оба (думать о причине - интересное упражнение). Таким образом, в вашем случае проверенная библиотека может иметь размер() как O (1) (в этом случае splice() будет O (n)) и, следовательно, может реализовать empty() с точки зрения размера(), не жертвуя производительностью, иначе это будет очень плохая библиотека.

Ответ 9

Предпочитаете использовать use empty(), чем size(), потому что каждый контейнер может реализовать пустую() реализацию по-другому, чтобы получить операцию с постоянным временем.

Пример:

вектор реализуется как:           bool empty() const       {//проверить, является ли последовательность пустой       return (size() == 0);       }

список реализуется как:

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