Параллелизм Java на практике имеет некоторую большую информацию о как к тестам записи на проблемы параллелизма. Однако они не истинные модульные тесты. Почти невозможно записать истинный модульный тест на проблему параллелизма.
В основном это сводится к этому. Создайте набор тестовых потоков и запустите их. Каждый поток должен
, поток junit создает все потоки и запускает их, затем считает в обратном порядке на первом фиксаторе однажды, чтобы позволить им всем пойти, затем ожидает второго фиксатора, затем делает некоторые утверждения об изменяемом состоянии.
Еще больше, чем другие типы ошибок, легче записать провальный модульный тест на ошибку параллелизма после , Вы нашли ошибку.
Adding will only work with random access iterators. std::advance
will work with all sorts of iterators. As long as you're only dealing with iterators into vectors, it makes no real difference, but std::advance
keeps your code more generic (e.g. you could substitute a list
for the vector
, and that part would still work).
For those who care, the standard describes advance
and distance
as follows (§24.3.4/1):
Since only random access iterators provide + and - operators, the library provides two function templates
advance
anddistance
. These function templates use+
and-
for random access iterators (and are, therefore, constant time for them); for input, forward and bidirectional iterators they use++
to provide linear time implementations.
Also note that starting with C++11, the standard added a parameter to std::next
, so you can advance by a specified amount using it (and std::prev
similarly). The difference from std::advance
is that it returns the modified iterator (which std::advance
doesn't), which can be convenient in some cases.
Это зависит от того, что вам нужно:
Если вам нужна универсальность , используйте std :: advance (it, 2)
. Если кто-то придет и изменит ваш std :: vector
на std :: list
, код все равно будет компилироваться, даже несмотря на то, что продвижение теперь требует линейного времени вместо постоянного времени.
Если вам нужна производительность , используйте it + = 2
. Если кто-то придет и изменит ваш std :: vector
на std :: list
, код не скомпилируется, указывая (возможно, с полезным комментарием) на серьезную проблему с производительностью. .
std::advance
works on non-random iterators too while the +=
version on works on random access sequences (vectors and the like).
It depends on the iterator. it=it+5
is faster if it's supported (it's only supported on random access iterators). If you want to advance a less-capable iterator (e.g. a forward iterator, or a bidirectional iterator), then you can use std::advance
, but it's slower because it actually walks across all of the intermediate elements.
std :: adnvance
является общим - он полезен, если вы не всегда знаете тип базового контейнера - он работает во всех случаях.
Тем не менее, он эффективен: std :: advance
выполнит оптимизацию, если он передал RandomAccessIterator (например, из std :: vector
), и увеличит итератор в цикле для ForwardAccessIterator (как в std :: список
).
Используйте std :: advance. Он столь же эффективен (он использует черты итератора просто для добавления итераторов для итераторов с произвольным доступом) и является более общим в том смысле, что он работает и с другими видами итераторов.
Если вы никогда не собираетесь менять контейнер (а вы, вероятно, не собираетесь этого делать), используйте +, потому что его легко увидеть и понять, а код не загроможден.
Если вы думаете, что хотите изменить контейнер, ИЛИ если вы работаете внутри шаблона, который может быть создан для различных типов контейнеров, используйте advance, потому что он работает с чем угодно.
Как правило, я не делаю этого. беспокоиться об изменении типов контейнеров, потому что я обнаружил, что, когда мне действительно нужно изменить тип контейнера, я в конечном итоге возвращаюсь везде, где этот контейнер используется, просто чтобы убедиться, что я не делаю ничего, что внезапно глупо (например, случайное выщипывание элементов из середины списка).