Является ли std :: string size () операцией O (1)?

Является ли std :: string size () операцией O (1)?

Реализация STL, которую я использую, встроена в VC++.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
26
0
13 652
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

size_type __CLR_OR_THIS_CALL size() const

{   // return length of sequence

    return (_Mysize);

}

Так что в конечном итоге может быть так, но никогда нельзя быть уверенным.

Я думаю, вы были отклонены, потому что вы не ответили на вопрос, вы потребовали от читателя соединить точки. К тому же ваш ответ непонятен.

mxcl 01.11.2008 23:59

Перефразирования не вижу. Для меня ответ все еще остается загадочным. «... в конце концов, это может быть так»? Разве этот код не был взят из реальной реализации?

Chap 10.07.2013 22:05

Да, std :: string :: size () равно O (1).

STL гарантирует производительность как минимум O (N) для контейнеров, однако многие контейнеры, включая std :: string, могут реализовать это как O (1) и будут. Обычно он либо возвращает простую переменную, либо выполняет что-то вроде _End - _Begin и возвращает это.

См. Таблицу 65 в Разделе 23.1 Стандарта. «a.size ()» отображается как «(Примечание A)», что говорит о том, что «Эти записи ... должны иметь постоянную сложность».

В разделе 21.3 говорится, что строки соответствуют требованиям последовательности (23.1), ipso facto size () является постоянным временем.

Ответ принят как подходящий

Если вы спрашиваете, имеет ли реализация MSVC string :: size () постоянную сложность, то ответ - да. Но Дон Уэйкфилд упомянул Таблицу 65 в 23.1 Стандарта C++, где говорится, что сложность size() должна соответствовать тому, что сказано в «Примечании A». Примечание A говорит:

Those entries marked ‘‘(Note A)’’ should have constant complexity.

Однако это не означает, что эти записи должен имеют постоянную сложность. В стандартах используется очень специфическая терминология, и «следует» означает, что это не обязательно.

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

Таким образом, вы не можете полагаться на то, что size() имеет постоянную сложность, но я, честно говоря, не уверен, есть ли какие-либо реализации, которые не имеют постоянного string::size().

В качестве примечания, тем не менее, можно получить размер строки как операцию O (1) стандартным способом: (end() - begin()). Это гарантированно будет [амортизировано] O (1), потому что и begin(), и end() должны быть O (1) (требования к контейнеру), итераторы строк имеют произвольный доступ (требования к строкам), а operator- должны быть O (1) для итераторов, которые поддержать его (требования к итератору).

Pavel Minaev 12.07.2009 12:22

... и длина строки не может быть вычислена из содержимого, поскольку нет ограничений на значения, которые могут быть сохранены. Это означает, что он должен управляться извне по отношению к содержимому и, таким образом, не зависит от N., то есть он должен быть О (1). Тот факт, что O(1) не является требованием к контейнерам все, не означает, что это может быть O(N) в контейнерах, только то, что может быть хотя бы один контейнер, для которого он не является постоянным, например std::list<>.

David Rodríguez - dribeas 27.10.2011 14:21

@ DavidRodríguez-dribeas: Хммм, возможно, можно использовать «кодировку» строки, чтобы избежать явного хранения длины где-либо. Например. используйте 0-байт в качестве escape-символа, значение которого зависит от следующего байта: 0 означает «конец строки», ненулевое значение означает «столько 0-байтов». Однако возможно, что другие требования std::string запрещают это (например, это означает, что индексирование массива больше не может быть O (1)).

j_random_hacker 17.11.2012 09:46

@j_random_hacker: Вы говорите о гипотетическом языке или C++? Говоря гипотетическим языком, я полагаю, что вы могли бы. В C++ стандарт 03 при описании std::basic_string<>::size() ссылается на требования к контейнеру (т.е. рекомендуемый постоянный размер), в стандарте 11 требование явное: Сложность: постоянное время.

David Rodríguez - dribeas 18.11.2012 03:05

@ DavidRodríguez-dribeas: Ты прав! В стандарте 03 21.3 / 2 говорится: «Шаблон класса basic_string соответствует требованиям Последовательности, как указано в (23.1.1)», а Последовательность - это тип контейнера (23.1.1 / 1), а контейнер требует постоянного времени begin() и end() (таблица 65 в 23.1). Рад слышать, что они сделали это явным в C++ 11.

j_random_hacker 18.11.2012 09:48

Строки @PavelMinaev не являются контейнерами. это известная причуда стандартизации. Я не верю, что ваша точка зрения остается в силе из-за этого.

v.oddou 10.01.2019 05:43

@PavelMinaev согласно этому stackoverflow.com/a/17259940/893406 Я не прав. Может быть, я запутался с вектором <bool> ... тогда не обращайте на меня внимания.

v.oddou 10.01.2019 05:47

Вот простой способ ответить на этот вопрос для msvC++.

Напишите код в проекте:

string happy;
happy.size();

Выделите вызов .size, щелкните правой кнопкой мыши, перейдите к определению.

При моей установке (vs2005sp1) это отправляет мне xstring: 1635, который выглядит так:

size_type __CLR_OR_THIS_CALL size() const
    {   // return length of sequence
    return (_Mysize);
    }

Итак, похоже, что у строки есть член с именем _Mysize, и он просто возвращает его.

Другими словами, это реализация O (1).

Но вопрос в том, как рассчитывается этот _Mysize?

Palak Jain 14.12.2019 20:03

Это член данных, поэтому он не вычисляется в функции .size (), он просто возвращается. Он изменяется, когда строка устанавливается, очищается, добавляется к и т. д.

tfinniga 15.12.2019 01:38

Для строки size() операция имеет должна быть постоянной для всех строковых реализаций, которые не используют веревки(1). В стандарте нет явного требования, которое требует, чтобы операция была O(1), наиболее близким является общее требование, чтобы size()должен был постоянным временем, но это оставляет место для любых других мер сложности.

Так почему должен это O (1)?

Это происходит из-за того, что размер не может быть вычислен из содержимого самой строки. В то время как в C вы используете терминатор NUL для определения конца строки, в C++ NUL так же действителен, как и любой другой символ в строке. Поскольку размер строки не может быть вычислен на основе content(2), он должен обрабатываться извне, независимо от фактического размера строки.

(1) Стандарт C++ 03 позволяет реализации использовать веревки в качестве реализации для строк, но факт в том, что ни одна из текущих реализаций стандартных библиотек не использует их.

(2) Если в реализации использовались веревки, операция могла бы зависеть от размера посредством количества блоков, из которых была построена веревка, если блоки были связаны через связанный список или аналогичную конструкцию, или если им было разрешено иметь разные размеры. Но веревки не используются ни в одной известной мне реализации стандартной библиотеки.

Сложность size()должен соответствует примечанию A. Это означает, что должен имеет постоянную сложность, то есть O (1). Хотя я не уверен в реализации, но итераторы в C++ действительно имеют связанные операции, такие как begin () и end (), которые указывают на контейнеры STL. Эти операции имеют постоянную временную сложность, поскольку они являются требованиями контейнера. Это означает, что begin() - end() также имеет постоянную сложность. Это означает, что size() - это операция O (1).

Другие вопросы по теме