Точка следования () — в программировании любая точка программы, в которой гарантируется, что все побочные эффекты предыдущих вычислений уже проявились, а побочные эффекты последующих ещё отсутствуют.

Точки следования часто упоминают, когда речь идёт о языках C и C++. В этих языках можно записать выражение, порядок вычисления подвыражений которого не определён стандартами и влияет на результат. Добавление одной или нескольких точек следования позволяет гарантировать порядок вычисления в некоторых случаях.

Стоит заметить, что подход к упорядочению процесса вычисления выражений на основе точек следования изначально достаточно хорошо отвечал потребностям языка C, но не являлся адекватным для языка C++, в котором был существенно расширен набор операторов, возвращающих lvalue-результаты. А с появлением необходимости языковой поддержки многопоточности в языках C и C++ от упорядочения на основе точек следования пришлось отказаться полностью. Современные спецификации языков C и C++ описывают упорядочение процесса вычисления выражений через отношения упорядочено до (sequenced before) и упорядочено после (sequenced after). Начиная со стандарта C++11, в языке C++ больше не существует понятия точки следования. В языке С понятие точки следования сохранилось по сей день, но, начиная со стандарта C11, не как фундаментальная концепция, а лишь как комбинация отношений упорядочено до и упорядочено после.

Стандарт C++11, а также последующие стандарты C++14 и C++17 внесли в операторы языка C++ большое количество дополнительных упорядочений на основе новой модели, что привело к тому, что многие выражения, поведение которых являлось неопределенным в C++98, получили вполне определённое поведение в современном C++. На сегодняшний день строгость упорядочения процесса вычисления выражений в языке C++ существенно превосходит таковую в языке C.

Примеры неоднозначности в языках C и C++ При наличии неоднозначностей стандарты языков C и C++: указывают несколько допустимых поведений из числа возможных (см. неуточняемое поведение); указывают единственно допустимое поведение из числа возможных либо явно указывают, что поведение не определено (см. неопределённое поведение).

Пример 1. Неуточняемое поведение.

g() + f() Оператор «» не является точкой следования, поэтому неизвестно, какая из функций будет вызвана первой: или . Поведение зависит от реализации компилятора.

Пример 2. Единственно допустимое поведение.

f(), g() Оператор «» является точкой следования, поэтому порядок вычисления гарантируется стандартом и известен заранее (слева направо): сначала вычисляется левый операнд: вызывается функция ; затем — правый: вызывается функция .

Пример 3. Неопределённое поведение.

i = ++i + i++ С точки зрения языка C указанное выражение содержит множественные модификации переменной , не упорядоченные относительно друг друга. Поведение данного выражения не определено (в то же время с точки зрения современного языка C++, который существенно более строго упорядочивает процесс вычисления оператора присваивания, поведение этого выражения полностью определено).

Точки следования в языках C и C++ В оригинальных стандартах языков C и C++ были определены следующие точки следования:

точки следования для операторов «&&», «||» и «,». Эти операторы гарантированно вычисляются слева направо, если не перегружены. Пример. В выражении «» сначала вычисляется левый операнд («»); результат приводится к типу и сравнивается с ; если равен , вычисляется правый операнд («»), иначе возвращается ;

точка следования для тернарного оператора «?:». 1-й операнд вычисляется первым; затем располагается точка следования; 2-й операнд вычисляется только, если 1-й операнд равен ; 3-й операнд вычисляется только, если 1-й операнд равен . Пример. В выражении «» сначала выполняется 1-й операнд («»; переменная увеличивается на ); результат вычисления приводится к типу и сравнивается с ; если равен , выполняется 2-й операнд («»), иначе — 3-й («0»);

точки следования в выражениях: на месте символа «» в выражениях, являющихся отдельными инструкциями. Например, в выражении «» точка следования вставляется вместо «»; в конце выражения, записанного после ключевого слова ; а точнее, на момент, когда возвращаемое значение будет скопировано в контекст вызывающей функции. Эта точка следования явно описана только в стандарте C++; в конце выражений, записанных в круглых скобках после ключевых слов , , (включая в конструкции do-while); в концах каждого из трёх выражений для цикла ;

перед вызовом функции. Порядок вычисления аргументов функции не определён. Точка следования гарантирует, что все аргументы будут вычислены до вызова функции. Пример. Рассмотрим выражение «». Сначала создаётся временная переменная со значением, равным значению переменной ; затем для переменной (не для временной) вызывается оператор «постфиксный ++»; наконец, вызывается функция  с временной переменной в качестве аргумента. Сказанное справедливо для переменных , и функций , соответственно. При этом из-за отсутствия точки следования у оператора «+» порядок вызова функций , и не определён. Следовательно, не определён и порядок вызова операторов «постфиксный ++» для переменных , и . То есть при выполнении функции не известно, были ли вызваны операторы «постфиксный ++» для переменных и . Пример. Рассмотрим выражение «». Запятая между аргументами функции не является оператором «запятая» и не гарантирует порядка вычисления значений аргументов. Порядок вычисления значений аргументов функции не стандартизован и зависит от реализации компилятора;

в объявлении с инициализацией на момент завершения вычисления инициализирующего значения. Пример. Рассмотрим выражение «». Точка следования вставляется после вычисления выражения «»;

перед вызовом перегруженного оператора в языке C++. Точка следования гарантирует вычисление значений аргументов оператора (как и обычной функции) до его вызова.

См. также Приоритеты операторов в C и C++

Примечания

Ссылки Точки следования (sequence points) Клаус Крэфт, Анжелика Лангер. Точки следования и вычисление выражений в C++ cppreference.com. Порядок вычислений в C и C++

Категория:Программирование