pigmeich: (Default)
[personal profile] pigmeich
... а тут меня еще и на раздумья о диапозонах потянуло.

Какая операция над C-строками одновременно частая и O(N) дорогая?

Вычисление длины строки. Особенно некрасиво получается если вы хотите перебрать строку с конца - приходится сначало до этого конца O(N) ехать.

И давно витала идея "а почему бы не хранить длину строки в специальной переменной". Действительно, почему бы и нет? Строки, обычно, занимают заметно больше 4-х байтового int, зато выростет производительность и по функции не надо будет таскать временную переменную с длиной строки.

Был и недостаток: принцип инкаспуляции не позволяет нам "выдавать" во вне класса хранилище строки. Вроде бы ничего страшного - можно наплодить друзей и методов.

Еще один недостаток: мы ограничиваем размер строки. Правда, ограничиваем где-то числом в 4Гб, что имеет смысл лишь на 64-битных системах. А на них и

Тем более, что позже придумали итераторы. А также в STL вошли алгоритмы.

И обнаружились два недостатка:
1. В алгоритмах диапозон указывается двумя итераторами на начало и конец, но проверка корректности, то есть принадлежности итераторов одному контейнеру и правильной последовательности, не производится.
Кроме того, такая передача неудобна с точки зрения наглядности кода:
Запись
 copy(it1, it2, it3); 

код не украшает.

2. В реализации алгоритмов почти повсеместно используется идиома просмотра последовательности
for(iterator = begin; iterator != end; ++iterator)
(кстати, если вычислять end() как begin + length и не поставить const получиться небольшое падение в скорости)
Такая запись удобна и с точки зрения производительности: операция итерации заменяется на разыменование. Но тут совсем не используется длина! Зачем же мы ее хранили.

Самое смешное, что длина нужна чтобы
1. организовать цикл с итерацией
2. получить доступ с конца строки
3. Определить размер буфера.

И только для 3-го пункта нужна именно длина. Для первых двух лучше подойдет указатель на конец буфера.

Итак, вместо указателя на начало сопряженного с длиной, мы храним два указателя - на начало и конец.

А поддиапозон, можно получить просто поставив указатели на родительский диапозон. Только для этого требуется константность хранилищ объектов. Проще говоря, семантика copy on write, либо неизменность контейнеров.

В .NET используется именно второй вариант. Кроме того, из-за отсутсвия проблем с управлением памятью неизменяемые строки почти автоматически становытся безопасны для передачи между потоками. А класс StringBuilder, служащий для изготовления новых строк, в спецификации нагло объявляется себя небезопасным с точки зрения потоков.




Тут у меня все не получается подойти к логическому концу, кроме того, время прижимает. Потому просто дам ссылки на свой код где сделанны #-подобные строки (это не рабочий прототип, просто мазки, вопросами правильного размещения счетчика ссылок я не задавался):

http://www.everfall.com/paste/id.php?4euuxsz84lsi
http://www.everfall.com/paste/id.php?5d42z63wnzdu
http://www.everfall.com/paste/id.php?t9562ixjkdmm

Date: 2007-12-20 12:35 pm (UTC)
From: [identity profile] zamotivator.livejournal.com
А хранения размера рядом с буфером порождает дополнительные проблемы - издержки на копирования при передаче во внешний вызов подстроки

Date: 2007-12-20 02:03 pm (UTC)
From: [identity profile] pigmeich.livejournal.com
А ты мой код смотрел?

Date: 2007-12-20 03:30 pm (UTC)
From: [identity profile] zamotivator.livejournal.com
В коде ничего относящегося к строкам я не увидел

Date: 2007-12-20 01:05 pm (UTC)
From: [identity profile] http://users.livejournal.com/_winnie/
http://russian.joelonsoftware.com/Articles/BacktoBasics.html

BSTR в COM хранит длину перед строкой.

ИМХО, лучше всего хранить отдельно, как раз ради фокуса о котором пишет [livejournal.com profile] zabivator

Date: 2007-12-20 02:31 pm (UTC)
From: [identity profile] pigmeich.livejournal.com
Так, ты тоже продолжения не дождался...

Date: 2007-12-20 01:33 pm (UTC)
From: [identity profile] pigmeich.livejournal.com
Блин!

Надо было мне залочить комменты пока я дописываю статью.

А ведь совсем к другому хотел подойти... =)

Date: 2007-12-20 02:34 pm (UTC)
From: [identity profile] http://users.livejournal.com/_winnie/
begin + end это почти тоже самое что begin + длина !

Date: 2007-12-20 03:30 pm (UTC)
From: [identity profile] zamotivator.livejournal.com
Ну позволь не согласиться.
Оно как минимум проблема с подстроками позволяет обойти

Date: 2007-12-20 03:33 pm (UTC)
From: [identity profile] http://users.livejournal.com/_winnie/
Когда итераторы random, то это вообще одно и тоже. Одно выводится из другого.
end = begin + длина
длина = end - begin

Date: 2007-12-20 03:37 pm (UTC)
From: [identity profile] zamotivator.livejournal.com
Гм, но проблемы в выборки подстроки тем не менее нету.
Просто потому что ты "длину" хранишь "отдельно" - передавая end

Date: 2007-12-21 03:14 am (UTC)
From: [identity profile] pigmeich.livejournal.com
абстракция другая.

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

Profile

pigmeich: (Default)
pigmeich

June 2017

S M T W T F S
    1 23
4 5678910
11121314151617
18192021222324
252627282930 

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 22nd, 2025 03:10 am
Powered by Dreamwidth Studios