c++ - Что означает «Предикаты не должны изменять свое состояние из-за вызова функции»?




c++11 stl (3)

Я читал в Интернете о C ++ и наткнулся на это утверждение:

Предикаты не должны изменять свое состояние из-за вызова функции.

Я не понял, что здесь означает «государство». Может кто-нибудь уточнить, пожалуйста, с примером?


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

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

  1. или один поток чередует вызовы

Давайте рассмотрим алгоритм std::count_if в качестве примера. Он пересекает диапазон и считает, как часто данный предикат оценивается как истинный. Далее предположим, что мы хотим проверить, сколько элементов в контейнере меньше заданного числа, например, 5 или 15.

Предикатом может быть много вещей. Это просто должно быть вызвано. Это может быть функтор:

struct check_if_smaller {
    int x;
    bool operator()(int y) { return y < x; }
};

Вы можете создавать различные экземпляры этого предиката, например, эти два

check_if_smaller a{5};
check_if_smaller b{15};

может использоваться для проверки, если числа меньше 5 или 15 соответственно:

bool test1 = a(3);  // true because 3 < 5
bool test2 = b(20); // false because 20 is not < 15

Член x является состоянием предиката. Обычно это не должно меняться при применении предиката (путем вызова его operator() ).

Из wikipedia :

В математической логике под предикатом обычно понимают булевозначную функцию P: X → {true, false}, называемую предикатом на X. Однако предикаты имеют много разных применений и интерпретаций в математике и логике, а также их точное определение , значение и использование будут варьироваться от теории к теории.

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


С точки зрения непрофессионалов, состояние в предикате является членом данных. Изменение состояния предикатом означает, что член get изменился во время выполнения алгоритма, и это изменение повлияет на поведение предиката.

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







predicate