В f (x) можно ли вычислить x до f?
у меня есть программа на языке C++. Эта программа делает что-то вроде этого:
struct MyT {void memfunc(std::unique_ptr<MyT> arg);};
std::unique_ptr<MyT> obj = /* some init */;
obj->memfunc(std::move(obj));
это гарантированно будет действительным, или я могу в конечном итоге вызвать функцию-член на nullptr
?
Стандартные котировки применимы.
Я знаю, что порядок оценки аргументов не имеет последовательности, но я не помню, что такое последовательность, т. е. вызываемый объект функции.
2 ответа:
Pre-C++17, это неопределенное поведение:
здесь цитата, которая доказывает, что все оценки, необходимые для вызова функции и связанных с ними побочных эффектов упорядочиваются перед вызовом функции.
Кроме того, все другие оценки, не имеющие конкретной последовательности, имеют неопределенную последовательность.
Это не накладывает каких-либо ограничений упорядочения на вычисляемые подвыражения, хотя по отношению друг к другу они остаются без последовательности по отношению к каждому другой.1.9 выполнение программы § 15
кроме тех случаев, когда отмечено,оценки операндов отдельных операторов и подвыражений отдельных выражений не имеют последовательности.
[...]
Вычисления значений операндов оператора упорядочиваются перед вычислением значений результата оператора. Если побочный эффект на скалярный объект не имеет последовательности относительно любой другой стороны влияние на один и тот же скалярный объект или вычисление значения используя значение одного и того же скалярного объекта, поведение не определено.
при вызове функции (независимо от того, является ли функция встроенной), каждое вычисление значения и побочный эффект, связанный с любым выражением аргумента или с постфиксным выражением, обозначающим вызываемую функцию, секвенируется перед выполнением каждого выражения или оператора в теле вызываемой функции.
[ Примечание: вычисление значений и побочные эффекты, связанные с различными выражениями аргументов, не имеют последовательности. -конец Примечание ]
каждое вычисление в вызывающей функции (включая другие вызовы функций), которое не имеет определенной последовательности до или после выполнения тела вызываемой функции, имеет неопределенную последовательность относительно выполнения вызываемой функции.9 несколько контекстов в C++ вызывают оценку вызова функции, даже если нет соответствующего появляется синтаксис вызова функции в блоке Перевод. [ ... ]
Ограничения последовательности на выполнение вызываемой функции (как описано выше)являются характеристиками оцениваемых вызовов функций, независимо от синтаксиса выражения, которое вызывает функцию.другие соответствующие цитаты о
std::move
template typename remove_reference:: type&& move(T & & t) noexcept;
Возвращается: static_cast(t). и
std::unique_ptr<T>.operator->()
:20.7.1.2.4 наблюдателей объекта unique_ptr
оператор указателя - > () const noexcept;
Требуется: получить() != nullptr.
Возвращает: получить().
memfunc
возвращает свой аргумент по значению, поэтому у нас есть 3 звонки:
а)obj->memfunc
б)std::move(obj)
c) конструктор перемещения переданного аргумента.
Потому что б) не меняется все, что угодно, мы можем игнорировать его для аргумента:a и c неопределенно упорядочены, поэтому любой из них может быть перед другим.
Если это произойдет, во-первых, все хорошо, с изменениемobj
не имеет значения.
Если С происходит, во-первых, оценивается с обнулятьсяobj
, нарушая предварительное условие, поэтому у нас есть UB.таким образом, это неопределенное поведение, потому что один из разрешенных ордеров имеет неопределенное поведение.
Post-C++17, это четко определено:
8.2.2 вызов функции [expr.звоните]
1 вызов функции-это постфиксное выражение, за которым следуют круглые скобки, содержащие возможно пустой, разделенный запятыми список инициализатор-п. которые составляют аргументы функции. [...]
[...]
5 The постфиксное-выражение расположено перед каждой выражение на expression-list и любой аргумент по умолчанию. [...]
[...]
Да, оценка
x
может происходить до, после или во время оценкиf
(они без последовательности).[ Примечание: оценки постфиксного выражения и выражений аргументов не имеют последовательности по отношению друг к другу. Все побочные эффекты оценок выражения аргумента упорядочиваются перед функцией вводится (см. 1.9). - на ]
(C++11, §5.2.2/8)