Конец () требуется быть постоянным в карте/наборе STL?

Подробно остановиться на ответе Ryan Doherty немного...

я работаю на статически типизированном языке на свое дневное задание (.NET/C#), а также Ruby как вещь стороны. До моего текущего дневного задания я был ведущим программистом для рубиновой фирмы по разработке выполнение работы для сервиса Синдикации Нью-Йорк таймс. Перед этим я работал в PHP также (хотя давным-давно).

я говорю что просто сказать это: я испытал направляющие (и в более общем плане рубин) проблемы производительности на собственном опыте, а также несколько других альтернатив. Как Ryan говорит, Вы не собираетесь иметь его, автоматически масштабируются для Вас. Это берет работу и огромные суммы терпения найти Ваши узкие места.

значительное большинство А производительности выходит, мы видели от других, и даже мы имели дело с медленными запросами выполнения в нашем уровне ORM. Мы пошли от Rails/ActiveRecord до Rails/DataMapper и наконец к Merb/DM, каждое повторение, получив больше скорости просто из-за базовых платформ.

Кэширование делает удивительные чудеса для производительности. К сожалению, мы не могли кэшировать наши данные. Наш кэш эффективно делался бы недействительным каждые пять минут самое большее. Почти каждый бит нашего сайта был динамичным. Таким образом, если/когда Вы не можете сделать этого, возможно, можно учиться на нашем опыте.

Мы должны были закончить тем серьезно, что точно настроили наши индексы базы данных, удостоверившись, что наши запросы не делали очень глупых вещей, удостоверяясь, что мы не выполняли больше запросов, чем было абсолютно необходимо, и т.д. Когда я говорю "очень глупые вещи", я имею в виду 1 + N проблема запроса...

#1 query
Dog.find(:all).each do |dog|
   #N queries
   dog.owner.siblings.each do |sibling|
      #N queries per above N query!!
      sibling.pets.each do |pet|
         #Do something here
      end
   end
end

DataMapper является отличным способом решить вышеупомянутую проблему (там , № 1 + N проблемы с ним ), но еще лучший путь состоит в том, чтобы использовать Ваш мозг и прекратить делать запросы как этот :D При необходимости в необработанной производительности большинство уровней ORM легко не обработает чрезвычайно пользовательские запросы, таким образом, Вы могли бы также вручить, пишут им.

Мы также сделали разумные вещи. Мы купили раскормленный сервер для нашей растущей базы данных и переместили ее прочь на свое собственное специализированное поле. Мы также должны были сделать ТОННЫ обработки и данных, импортирующих постоянно. Мы переместили нашу обработку прочь на собственное поле также. Мы также прекратили загружать наш весь долбаный стек только для наших утилит импорта данных. Мы со вкусом загрузили только, в чем мы абсолютно нуждались (таким образом сокращение памяти наверху!).

, Если Вы не можете сказать уже... обычно, когда дело доходит до ruby/rails/merb, необходимо масштабироваться , бросив аппаратные средства в проблему. Но в конце, аппаратные средства являются дешевыми; хотя это не оправдание за дрянной код! :D

И даже с этими трудностями, я лично никогда не запускал бы проекты в другой платформе, если я могу помочь ей. Я люблю язык, и постоянно узнавайте больше о нем каждый день. Это - что-то, что я не получаю от C#, хотя C# быстрее.

я также наслаждаюсь инструментами с открытым исходным кодом, низкая стоимость, чтобы начать работать на языке, низкая стоимость, чтобы просто получить что-то там и попытаться видеть, востребовано ли это рынком, все время работающий на языке, что часто времена могут быть изящными и прекрасными...

В конце, это - все о том, что Вы хотите жить, вдохнуть, поесть, и сон в изо дня в день когда дело доходит до выбора Вашей платформы. Если Вам нравится образ мыслей Microsoft, пойдите.NET. Если Вы хотите открытый исходный код, но все еще хотите структуру, попробуйте Java. Если Вы хотите иметь динамический язык и все еще иметь немного больше структуры, чем рубин, попробуйте Python. И если Вы хотите элегантность, попробуйте Ruby (я шучу, я шучу... существует много других изящных языков, которые отвечают всем требованиям. Не пытаясь запустить войну пламени :D)

Черт, судите их всех! Я склонен соглашаться с ответами выше того волнения по поводу оптимизации, рано не причина, Вы должны или не должны выбирать платформу, но я не соглашаюсь, что это - их единственный ответ.

Так короче говоря, да существуют трудности, которые необходимо преодолеть, но элегантность языка, по моему скромному мнению, явно перевешивает те недостатки.

Извините за роман, но я был туда и обратно с проблемами производительности. Это может быть преодоленным. Не позволяйте этому отпугнуть Вас.

34
задан suszterpatt 16 September 2009 в 11:53
поделиться

9 ответов

Вы можете использовать немного магии Reflection :

public function loadFromArray($array) {
    $class = new ReflectionClass(get_class($this));
    $props = $class->getProperties();
    foreach($props as $p) {
         if (isset($array[$p->getName()])
              $p->setValue($this, $array[$p->getName]);
    }
}

Вы можете реализовать этот метод в базовом классе и сделать все ваши объекты наследуемыми от него, так что у вас есть это функциональность в каждом объекте без повторения в любом классе.

(например, объекту на карте), этот итератор останется действующим, несмотря на вставку и удаление элементов. Предполагая, что std :: map :: end () получает «итератор в карту», ​​он не должен быть признан недействительным путем вставки / удаления.

Это, конечно, оставляет вопрос, означает ли «не признан недействительным» всегда одно и то же значение. Мое личное предположение, что это не указано. Однако для того, чтобы фраза «не признана недействительной» имела смысл, все результаты std :: map :: end () для одной и той же карты всегда должны сравниваться равными даже на первый взгляд. of вставки / удаления:

my_map_t::iterator old_end = my_map.end();
// wildly change my_map
assert( old_end == my_map.end() ); 

Моя интерпретация такова, что если old_end остается «действительным» при всех изменениях карты (как стандартные обещания), то это утверждение должно пройти.

Заявление об ограничении ответственности : Я не являюсь носителем языка, и мне очень трудно переварить этот ужасный легалез Священного PDF. На самом деле вообще я избегаю этого как чумы.

О, и моя первая мысль тоже была: вопрос интересен с академической точки зрения, но почему он просто не хранит ключи вместо итераторов?

5
ответ дан 27 November 2019 в 17:16
поделиться

23.1 / 7 говорит, что end () возвращает итератор, который

является последним значением для контейнера.

Во-первых, он подтверждает, что end () возвращает итератор. Во-вторых, он говорит, что итератор не указывает на конкретный элемент. Поскольку удаление может сделать недействительными только итераторы, которые куда-то указывают (на удаляемый элемент), удаления не могут сделать недействительными end () .

.
4
ответ дан 27 November 2019 в 17:16
поделиться

Well, there's nothing preventing particular collection implementation from having end() depend on the instance of collection and time of day, as long as comparisons and such work. Which means, that, perhaps, end() value may change, but old_end == end() comparison should still yield true. (edit: although after reading the comment from j_random_hacker, I doubt this paragraph itself evaluates to true ;-), not universally — see the discussion below )

I also doubt you can use std::map::iterator in the Node class due to the type being incomplete, yet (not sure, though).

Also, since your nodes are uniquely numbered, you can use int for keying them and reserve some value for invalid.

3
ответ дан 27 November 2019 в 17:16
поделиться

Предполагая, что (1) карта реализована с помощью красно-черного дерева (2) вы используете тот же экземпляр «после миллиарда вставок / удалений» - ответьте «Да».

Относительное внедрение Я могу скажите, что все воплощения stl, которые я когда-либо знал, используют древовидный алгоритм.

1
ответ дан 27 November 2019 в 17:16
поделиться

Пара замечаний:

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

2) Я думаю, что, возможно, ваша идея о хранении массива из 4 итераторов в узле может быть изменена, чтобы решить проблему в целом. смысл. Вам нужно добавить новый тип итератора к объекту Graph, который может выполнять итерацию по соседям одного узла. Реализация этого итератора потребует доступа к членам карты, что, возможно, приведет вас к тому, что класс Graph расширит коллекцию карт.

1
ответ дан 27 November 2019 в 17:16
поделиться

Это может зависеть от используемого вами внешнего вида, но для меня шрифт Swing по умолчанию -

DejaVu Sans - Plain

Для большинства компонентов размер шрифта по умолчанию составляет около 12 или 13

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

1
ответ дан 27 November 2019 в 17:16
поделиться

Стандарт C ++ гласит, что итераторы должны оставаться действительными. И это. Стандарт четко указывает, что в 23.1.2 / 8:

элементы вставки не должны влиять на действительность итераторов и ссылок на контейнер , а также элементы erase должны аннулировать только итераторы и ссылки на удаленные элементы.

И в 21.1 / 7:

end () возвращает итератор , который является последним значением для контейнер .

Таким образом, итераторы old_end и new_end будут действительными. Это означает, что мы могли бы получить - old_end (назовите его it1 ) и - new_end (назовите его it2 ), и он будет быть итераторами конечного значения (из определения того, что возвращает end () ), поскольку итератор ассоциативного контейнера относится к категории двунаправленного итератора (согласно 23.1.2 / 6) и согласно определению операции - r (Таблица 75).

Теперь it1 должен быть равен it2 , поскольку он дает конечное значение, которое равно единице (23.1.2 / 9). Тогда из 24.1.3 следует, что: Условие, что a == b подразумевает ++ a == ++ b . И ++ it1 и ++ it2 будут давать итераторы old_end и new_end (из определения операции ++ r в таблице 74). Теперь мы получаем, что old_end и new_end должны быть равными .

Теперь it1 должен быть равен it2 , поскольку он дает конечное значение, которое равно единице (23.1.2 / 9). Тогда из 24.1.3 следует, что: Условие, что a == b подразумевает ++ a == ++ b . И ++ it1 и ++ it2 будут давать итераторы old_end и new_end (из определения операции ++ r в таблице 74). Теперь мы получаем, что old_end и new_end должны быть равными .

Теперь it1 должен быть равен it2 , поскольку он дает конечное значение, которое равно единице (23.1.2 / 9). Тогда из 24.1.3 следует, что: Условие, что a == b подразумевает ++ a == ++ b . И ++ it1 и ++ it2 будут давать итераторы old_end и new_end (из определения операции ++ r в таблице 74). Теперь мы получаем, что old_end и new_end должны быть равными .

И ++ it1 и ++ it2 будут давать итераторы old_end и new_end (из определения операции ++ r в таблице 74). Теперь мы получаем, что old_end и new_end должны быть равными .

И ++ it1 и ++ it2 будут давать итераторы old_end и new_end (из определения операции ++ r в таблице 74). Теперь мы получаем, что old_end и new_end должны быть равными .

0
ответ дан 27 November 2019 в 17:16
поделиться

Итераторы в (мульти) наборах и (мульти) картах не будут аннулируется при вставках и удалениях, и поэтому сравнение .end () с предыдущими сохраненными значениями .end () всегда будет давать значение true .

Возьмем для примера реализацию GNU libstdc ++, где .end () в картах возвращает инициализированное значение по умолчанию Rb_tree_node

Из stl_tree.h:

  _M_initialize()
  {
    this->_M_header._M_color = _S_red;
    this->_M_header._M_parent = 0;
    this->_M_header._M_left = &this->_M_header;
    this->_M_header._M_right = &this->_M_header;
  }
1
ответ дан 27 November 2019 в 17:16
поделиться

Я считаю, что это полностью зависит от того, какой тип итератора используется.

В векторе end () стоит за указателем конца, и он, очевидно, будет меняться по мере вставки и удаления элементов.

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

Я считаю, что итераторы set и map являются вторым типом, но я не знаю ничего, что требовало бы их реализации в туда.

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

Я считаю, что итераторы set и map являются вторым типом, но я не знаю ничего, что требовало бы их реализации в туда.

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

Я считаю, что итераторы set и map являются вторым типом, но я не знаю ничего, что требовало бы их реализации в туда.

0
ответ дан 27 November 2019 в 17:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: