- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
#include <iostream>
#include <string>
int main()
{
std::string s1 = "";
const char s2[] = "";
std::cout << std::boolalpha
<< std::empty(s1) << std::endl
<< std::size(s1) << std::endl
<< std::empty(s2) << std::endl
<< std::size(s2) << std::endl;
s1.assign("", 1);
std::cout << std::empty(s1) << std::endl
<< std::size(s1) << std::endl;
system("pause");
return 0;
}
666_N33D135 11.08.2018 05:40 # +1
guest8 11.08.2018 08:16 # −999
bormand 11.08.2018 08:36 # +1
У std::string есть поле с длиной и она может хранить нолики посреди строки.
Но строковые литералы в языке остались сишные, поэтому "" это в реальности массив из одного '\0'. А у std::string в конструкторе с одним параметром есть костыль -- копируются только символы до первого нолика. Иначе юзать std::string было бы неудобно.
В строке 15 заюзали другой конструктор, в который длина передаётся явно и получился std::string, который содержит один символ '\0'.
j123123 11.08.2018 12:58 # 0
Нет чтоб сделать единый контейнер для подобного говна, и добавить б там каких-нибудь конструкторов, ну чтоб можно было там способ аллокации выбирать (если говорить про std::vector и std::array чтоб каким-то там параметром передавалось то, хотим ли мы статический массив или рантайм-вектор)
gost 11.08.2018 13:20 # 0
Ну а в "Modern C++" это вообще как-то некуда впихивать, в том числе из-за подобного сахара:
UPD: а для строк так вообще нужны специфические методы, типа того же find'а, split, join... - в интерфейсе вектора это всё нинужно.
j123123 11.08.2018 13:32 # 0
Да ладно, а если мне надо последовательность из четырех флоат чисел в векторе из флоатов найти?
gost 12.08.2018 05:33 # 0
Ну а то, что цэпэпэшная "строка" - говно несусветное, известно уже давно и, похоже, всем.
j123123 25.08.2018 02:25 # 0
upper/lower/swapcase должны быть не методами контейнера, а методами для типов, всунутых в контейнер (контейнеру незачем знать, что за говно в нем хранится). Ну типа можно тупым циклом или через std::for_each пробежать вектор или строку, и чтоб можно было и upper/lower/swapcase к каждому сделать (что имеет смысл для "букв") и для каждого числа abs() сделать например (что имеет смысл для знаковых чисел, но не имеет смысла для беззнаковых) или возвести в квадрат (что имеет смысл и для знаковых и для беззнаковых).
Собственно к чему я? А, да. Вот на кой хер собственно делать специальный контейнер для именно массива из "букв"? Только чтоб нолик дописать? Делать upper/lower/swapcase методом самого контейнера? Тьфу! Давайте уж тогда сделаем контейнеры отдельно для беззнаковых и знаковых чисел, и тогда только в контейнере для знаковых будет abs(), ну не охуенно ли?
roman-kashitsyn 25.08.2018 12:15 # 0
Потому что компьютер ничего не знает о "буквах". Компьютер знает о байтах. Если тебе нужны "буквы", то контейнер для них нужно аккуратно спроектировать (std::string не является хорошим примером).
Один из наилучших и наиболее компактных способов — хранить строки как иммутабельные массивы байтов, представляющие кодпоинты, заэнкоженые в UTF-8.
Только сырые байты из такой строки торчать не должны. to_upper / to_lower тоже специально делать не нужно, достаточно итераторов, которые перебирают кодпоинты, и общих оптимизированных функций вида to_upper/to_lower/swapcase и прочие операции можно выразить тривиально как Модифицировать utf-8 строки in-place в общем случае нельзя (функция transliterate может менять размер контейнера).
Подытожим:
• специальный контейнер для строк — отличная идея.
• реализация std::string в плюсах — говно, потому что UTF-8 тогда ещё не придумали, и юникод был не так повсеместен.
j123123 25.08.2018 16:09 # +1
Лучше хранить в UTF-32 - так мы избавимся от питушни, связанной с посимвольным проматыванием в итераторах, и все сведется к обычному uint32_t массиву, который можно напрямую индексировать.
Ну а если у нас мало оперативки, можно конечно и UTF-8. Только вот что насчет UTF-16, которая тоже с переменной длиной символов? А есть еще китайская кодировка GB 18030, где тоже та же хрень. К тому же в подобной хуйне в теории можно было б хранить последовательность инструкции процессора, если процессор может в инструкции переменной длины (как например в x86) чтоб их проматывать через дизассемблер длин. По-моему было б логичнее просто сделать иммутабельный кусок байт, и сделать типа специализацию чтоб туда мог приделываться итератор для проматывания UTF-8, UTF-16, GB 18030, машинного кода x86 или любой другой подобной хуйни, чем делать по контейнеру для любой хрени переменного размера в котором размер каждой хрени можно посчитать на основе значения этой самой хрени (как в UTF-8, UTF-16, GB 18030, x86 машкода и проч...)
roman-kashitsyn 25.08.2018 22:46 # 0
Иногда лучше, иногда нет. Сконвертировать всегда можно при необходимости, это тривиально при наличии итератора.
> что насчет UTF-16
нинужен
> Ну а если у нас мало оперативки, можно конечно и UTF-8.
UTF-8 лучше не только для оперативки, но и для пирфоманса. Так лучше small-string optimization работать будет, больше полезных данных в кэш помещаться будет.
Более того, в оперативке твои строки никому не нужны, когда ты будешь какой-нибудь HTML отдавать, всё равно в UTF-8 конвертировать придётся, так зачем конвертить?
> По-моему было б логичнее просто сделать иммутабельный кусок байт
Кто будет помнить кодировку, царь? Пусть уж из типа будет понятно, в какой кодировке там всё лежит.
j123123 25.08.2018 23:38 # +1
Далеко не факт. В UTF-8 найти какое-нибудь слово будет сложнее, некоторые алгоритмы поиска подстроки работают довольно хитровыебаным способом, и необходимость раздрачивать всю последовательность UTF-8 чтоб получить какой-то там символ в N-ной позиции делает эти алгоритмы попросту непрактичными, и приходится использовать более хуевые алгоритмы. То же самое касается заматчивания регулярок. UTF-8 очень хуев, когда в нем надо что-то искать.
> Кто будет помнить кодировку, царь? Пусть уж из типа будет понятно, в какой кодировке там всё лежит.
Да без проблем
typedef immutabelny_kusok_byteov utf8_string
и потом делать функции, которые принимают utf8_string в качестве аргумента и что-то там с ними делают, а если пихать этим функциям immutabelny_kusok_byteov то будет варнинги или вообще не скомпилируется
roman-kashitsyn 25.08.2018 23:53 # 0
Нет, тайпдеф не так работает.
j123123 26.08.2018 00:02 # 0
Я знаю. Но наверняка можно сделать чтоб работал (запатчить в компиляторе хрень какую-нибудь). Или тупо в struct {} обернуть.
bormand 26.08.2018 08:58 # 0
... когда в нём надо что-то менять.
А искать нормально должно. Откатываться на запомненные позиции легко даже с utf-8.
bormand 26.08.2018 09:02 # 0
С регулярками сложнее, но тоже можно конпелять автомат так, чтобы он прямо над байтами работал.
guest8 26.08.2018 09:55 # −999
bormand 26.08.2018 10:18 # 0
А оно надо? Подстрока и с байтовыми оффсетами нормально выдернется.
З.Ы. Большинству алгоритмов от строки нужны только итераторы, а не произвольный доступ к символам.
j123123 26.08.2018 19:07 # 0
bormand 26.08.2018 19:09 # 0
Ну т.е. один хуй пробежать по всем символам?
j123123 26.08.2018 19:12 # 0
j123123 26.08.2018 19:17 # 0
defecate-plusplus 26.08.2018 19:32 # 0
только ведь и UCS-32 тебе не поможет закодировать залго так, чтобы 4 * число букв совпало с числом байт (проверь)
что порекомендуешь? UCS-256? UCS-1024?
bormand 26.08.2018 19:34 # 0
Массив из указателей на символы.
j123123 26.08.2018 20:05 # 0
g0cTb 25.08.2018 13:05 # 0
Ну вот в numpy или матлабе так и поступили: сделали контейнеры для чисел с арифметическими операциями. Поэтому учоные пользуются ими, а не сишечкой. А логи парсят питоном и перлом, а не сишечкой.
Потому что если тебе надо каждый день преобразовывать строки в верхний регистр, то удобнее для этого иметь одну функцию, а не for_each+toupper.
bormand 11.08.2018 13:46 # +2
> строка
Если бы не костыль с c_str(), то эту хуету с чистой совестью можно было бы назвать ByteArray. Там больше ни одного специфичного для строк метода нету.
roman-kashitsyn 11.08.2018 14:45 # 0
Насколько я помню, основное отличие строки от вектора в том, что содержимое строк должно быть всегда тривиально копируемо memcpy, якобы это позволяло сделать более простую и эффективную реализацию, но пруфов сходу не найду.
bormand 11.08.2018 14:48 # 0
А для вектора из POD'ов подобная оптимизация нинужна?
roman-kashitsyn 11.08.2018 14:58 # 0
bormand 11.08.2018 15:16 # 0
bormand 11.08.2018 15:20 # 0
Steve_Brown 13.08.2018 10:48 # +1
--
* за исключением случая, когда QByteArray инициализируется константными данными без копирования. Если возможна такая ситуация, лучше использовать data(), который при необходимости нолик допишет.
gost 13.08.2018 11:17 # +1
§ 24.3.2.5 (N4659)
§ 24.3.2.7.1 (N4659)
Диапазон [0, size()] - закрытый, поэтому последний элемент у массива, возвращаемого data/c_str - charT(), что для std::string эквивалентно char() - то есть 0.
HighVoltageCock 13.08.2018 12:03 # +1
Steve_Brown 13.08.2018 13:06 # 0
Раскрываем reference operator[](size_type pos). Поскольку !(pos < size()), это будет:
А, так оно вернет ссылку на терминатор. Все ясно.
Хитро сформулировано. А то я из описания operator[] решил, что можно было бы не хранить \0, а возвращать ссылку на какой-то статический нолик...
HighVoltageCock 13.08.2018 13:22 # 0
gost 11.08.2018 13:29 # 0
bormand 11.08.2018 13:57 # +1
Чтобы ты заебался всё это учить. Ты ещё спроси, почему вместо std::vector<bool> получается какая-то невменяемая хуйня с битоёбством.
vistefan 13.08.2018 14:41 # 0
Упаковка что ли? А как тогда указатель на элемент брать?
nojloBou_xyu 13.08.2018 17:24 # 0
bormand 11.08.2018 08:45 # 0
З.Ы. Ну да, ты прав. Первая -- крестовая std::string с длиной ноль. И вторая, унаследованная от сишечки -- массив из 1 байта со значением '\0'.
guest8 11.08.2018 10:35 # −999
guest8 11.08.2018 10:36 # −999
bormand 11.08.2018 10:39 # +1
Ты про const char s2[]? Ну да, это массив инициализированный сишным строковым литералом "" (т.е. одним байтом со значением '\0'). std::size() обработало его как и любой другой массив.
666_N33D135 11.08.2018 15:34 # 0
bormand 11.08.2018 15:53 # 0
З.Ы. Ещё не стоит путать size и sizeof. sizeof -- размер в байтах, size -- количество элементов.
g0_1494037117303 11.08.2018 17:32 # 0
Типа умный?
bormand 11.08.2018 17:32 # 0
guest8 11.08.2018 17:44 # −999
guest8 11.08.2018 17:49 # −999
bar-u-xoloda 11.08.2018 18:42 # 0
bormand 11.08.2018 18:46 # 0
bar-u-xoloda 11.08.2018 18:49 # 0
bormand 11.08.2018 18:59 # +1
guest8 11.08.2018 23:38 # −999
guest8 12.08.2018 00:40 # −999
guest8 12.08.2018 01:15 # −999
gost 12.08.2018 05:44 # 0
Метушнёй со SFINAE.
gost 12.08.2018 06:17 # 0
Или, если хочется выебнуться получить сообщение об ошибке:
guest8 12.08.2018 11:37 # −999
gost 12.08.2018 12:27 # 0
Ну, это их проблемы:
§ 5.13.5, 8 (N4659).
С Watcom странно, видимо, он тоже считает строковые литералы указателями.
guest8 12.08.2018 14:18 # −999
guest8 12.08.2018 12:07 # −999
guest8 12.08.2018 12:16 # −999
real_escape_string 13.08.2018 23:48 # 0
gost 14.08.2018 07:42 # 0
guest8 14.08.2018 09:31 # −999
gost 14.08.2018 09:47 # 0
Читать далее: https://en.cppreference.com/w/cpp/language/partial_specialization, раздел "Partial ordering".
gost 12.08.2018 06:30 # 0
Это что там такого MSVC в std::string накидала? Указатель на начало (8), размер (8) - а ещё что?
И, главное, как шланг смог в 4 байта?
P.S. Лол, на моей визуалке std::string весит 32 байта в релизном x64 режиме и 40 в отладочном. Ну и жирнота...
bormand 12.08.2018 07:38 # 0
guest8 12.08.2018 11:12 # −999
gost 12.08.2018 12:17 # 0
bar-u-xoloda 12.08.2018 12:21 # 0
guest8 12.08.2018 13:35 # −999
666_N33D135 12.08.2018 15:25 # 0
Поговорил бы кто со мной,
А то мои подружки - пиявки,да лягушки!
Фу, какая гадость!
Эх, жизнь моя - жестянка!
Да ну ее в болото!
Живу я как поганка,
А мне летааааать, а мне летааааать, а мне летать охота!
bar-u-xoloda 12.08.2018 17:42 # 0
roskomgovno 12.08.2018 17:51 # 0
guest8 12.08.2018 23:12 # −999
guest8 27.08.2018 23:17 # −999
bormand 27.08.2018 23:19 # 0
guest8 27.08.2018 23:42 # −999
roman-kashitsyn 27.08.2018 23:25 # 0
не должны быть, это просто наиболее очевидная реализация. Можно, к примеру, обойтись и одним указателем, если все данные на куче выделять:
bormand 27.08.2018 23:26 # 0
Можно и char data[1]. Меньше аллокаций.
roman-kashitsyn 27.08.2018 23:48 # 0
Спасибо, именно это я и хотел написать, а написал вместо этого херню на автомате.
guest8 27.08.2018 23:54 # −999
roman-kashitsyn 28.08.2018 00:07 # 0
bormand 28.08.2018 00:23 # 0
Указатель сразу на буфер, немного инструкций сэкономится.
roman-kashitsyn 28.08.2018 00:34 # 0
Тебе почти для многих действий нужно знать длину, всё что тут наэкономилось в трубу вылетит сразу.
Хотя, в яндексовой стандартной строке похожая оптимизация запилина
Desktop 28.08.2018 00:36 # 0
bormand 28.08.2018 00:36 # 0
bormand 28.08.2018 00:42 # 0
guest8 28.08.2018 01:03 # −999
guest8 28.08.2018 01:09 # −999
bormand 28.08.2018 08:12 # 0
guest8 28.08.2018 00:41 # −999
3.14159265 28.08.2018 03:15 # −1
g0_1494078705717 28.08.2018 03:19 # 0
3.14159265 28.08.2018 03:21 # −1
>сайт выглядит днищнее любого другого форума по программированию
http://risovach.ru/upload/2013/05/mem/neytan_20159986_orig_.jpeg
bormand 28.08.2018 08:03 # +1
Андеграунд, хули.
shite 13.08.2018 18:01 # 0