Std:: lower_bound и std:: find на простом массиве

Мне нравится использовать std::algorithm всякий раз, когда я могу использовать простые массивы. Теперь у меня есть 2 сомнения; Предположим, я хочу использовать std::lower_bound, что произойдет, если значение, которое я предоставляю в качестве аргумента, не найдено?

int a[] = {1,2,3,4,5,6};
int* f = std::lower_bound(a,a+6,20);

Результат при печати * f равен 20.

То же самое происходит, если я использую std::find.

int a[] = {1,2,3,4,5,6};
int* f = std::find(a,a+6,20);

Результат при печати * f равен 20.

  • Всегда ли возвратное значение является исходным аргументом когда это не найдено?
  • С точки зрения производительности std::lower_bound работает лучше std::find, поскольку он реализует алгоритм бинарного поиска. Если массив большой, скажем, максимум 10 элементов, может ли std:: find работать лучше? За кулисами std:: lower_bound звонки std:: advance и std:: distance.. можно также сохранить эти вызовы?

Спасибо большое

AFG

Ответ 1

В результате у меня есть 20. (Позже отредактировано: результат, который у меня есть при печати * f равен 20.)

Нет, результат: a+6. Dereferncing, который вызывает поведение undefined. Он может печатать 20, он может печатать "Shirley MacLaine", или это может взорвать ваш автомобиль.

Всегда ли возвращаемое значение является исходным аргументом, если оно не найдено?

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

Из cppreference.com возвращаемое значение std:: lower_bound - это "итератор", указывающий на первый элемент, который не меньше value, или last, если такой элемент не найден. "

С точки зрения производительности...

Измерьте это. Никакой другой совет здесь не будет соответствовать вашим фактическим эмпирическим доказательствам.

За кулисами std:: lower_bound звонки std:: advance и std:: distance..может ли я также сохранить эти вызовы?

Почти наверняка нет. Эти вызовы почти наверняка оптимизированы в вашем случае для одиночных (или очень немногих) инструкций.

Ответ 2

В вашем примере вы не должны разыгрывать f, потому что он равен a+6. В любом случае, вы находитесь на территории UB, но я полагаю, что значение 20 находится в стек сразу после массива a.

Верно, что для небольших массивов линейный поиск может быть быстрее, чем двоичный поиск. 10 "маленький", а не "большой". Если у вас есть программа, которая выполняет множество поисков в небольших массивах, вы можете просмотреть их каждый раз.

Для std::advance и std::distance не должно быть накладных расходов - любой полукомпетентный компилятор С++ будет встраивать все, и они превратятся в сложение и вычитание указателя.

Ответ 3

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