Существует ли гарантированное отношение «происходит до» для оценки аргумента к цепочечным методам? - PullRequest
2 голосов
/ 27 октября 2011

Я хочу обрезать строку в C ++ с помощью этого кода:

std::string str("  Trim test   ");
str.erase(                                 /* 1 */
          0,                               /* 2 */
          str.find_first_not_of(" ")       /* 3 */
         )                                 /* 4 */
   .erase(                                 /* 5 */
          str.find_last_not_of(" ") + 1,   /* 6 */
          std::string::npos                /* 7 */
         );                                /* 8 */

Позволяет ли стандартная строка № 6 вычисляться до выполнения строки № 1, чтобы, когда № 5 был наконец вызванаргумент больше не может быть действительным?

Ответы [ 2 ]

3 голосов
/ 27 октября 2011

Да, стандартная разрешающая строка № 6 рассчитывается до выполнения строки № 1.

С страница Википедии о точках последовательности :

[Точки последовательности происходят] Перед вводом функции в вызове функции. Порядок, в котором оцениваются аргументы, не указан, но эта точка последовательности означает, что все их побочные эффекты завершены до ввода функции. В выражении f (i ++) + g (j ++) + h (k ++), f вызывается с параметром исходного значения i, но i увеличивается до ввода тела f. Аналогично, j и k обновляются перед вводом g и h соответственно. Однако не указано, в каком порядке f (), g (), h () выполняются, и в каком порядке i, j, k увеличиваются. Переменные j и k в теле f могут быть или не быть уже увеличены. Обратите внимание, что вызов функции f (a, b, c) не является использованием оператора запятой, и порядок вычисления для a, b и c не определен.

Вы должны переписать его как

str.erase(0, str.find_first_not_of(" "));           

str.erase(str.find_last_not_of(" ") + 1, std::string::npos);     
1 голос
/ 27 октября 2011

Да, 6 можно вызвать раньше 1.

Однако код может быть переставлен так, чтобы он не имел значения:

std::string str("  Trim test   ");
str.erase(                                 /* 1 */
          str.find_last_not_of(" ") + 1,   /* 2 */
          std::string::npos                /* 3 */
         )                                 /* 4 */
   .erase(                                 /* 5 */
          0,                               /* 6 */
          str.find_first_not_of(" ")       /* 7 */
         );                                /* 8 */

Нет гарантии, что 7 не будет вызываться раньше 1, но это не имеет значения , так как индекс все еще действителен.
Имейте в виду, что много в одной строке - плохая идея, и должно быть как минимум 4 отдельными строками.

...