Каков порядок вызова деструкторов для временных в C ++?

Рассмотрим следующий код:

#include <iostream>

struct A {
~A() { std::cout << "~A" << std::endl; }
};

struct B {
~B() { std::cout << "~B" << std::endl; }
};

struct C {
~C() { std::cout << "~C" << std::endl; }

void operator<<(const B &) {}
};

C f(const A &a = A()) {
return C();
}

int main() {
f(A()) << B();
}

Компиляция с GCC и выполнение дает следующий вывод:

~C
~A
~B

Гарантируется ли, что деструкторы для временных объектов типов A, B и C будут вызываться в этом порядке при компиляции с другими компиляторами? В общем, каков порядок вызовов деструкторов для временных, если они есть?

5

Решение

Давайте поговорим о подвыражениях и их последовательности. Если E1 является последовательность перед E2, это означает E1 должны быть полностью оценены до E2 является. Если E1 является без последовательности с E2, это означает E1 а также E2 может оцениваться в любом порядке.

За f(A()) << B(), который в вашем случае так же, как f(A()).operator<<(B()), мы знаем это:

  • A() последовательность перед f(...),
  • f(...) последовательность перед operator<< а также
  • B() последовательность перед operator<<

Это также говорит нам о том, что:

  • A() последовательность перед operator<<
  • A() не секвенируется с B()
  • f(...) не секвенируется с B()

Если мы предполагаем RVO, чтобы не усложнять ситуацию, возможный порядок, в котором компилятор может оценивать подвыражения в:

  • A() -> f(...) -> B(), уступая ~B() -> ~C() -> ~A()
  • A() -> B() -> f(...), уступая ~C() -> ~B() -> ~A()
  • B() -> A() -> f(...), уступая ~C() -> ~A() -> ~B()

Последний порядок наблюдается в ОП. Обратите внимание, что порядок уничтожения всегда является обратным порядком построения.

10

Другие решения

Порядок оценки выражения f(A()) << B(); не указано Таким образом, порядок строительства / уничтожения также не указан.

3

Порядок оценки операндов << не указано Следовательно, порядок не гарантируется. Только операторы короткого замыкания &&, ||троичный оператор ?:и запятая , Оператор имеет четко определенный порядок вычисления операндов. Для других нет необходимости, чтобы левый операнд оценивался перед правым операндом (или наоборот).

Кроме того, не путайте приоритет оператора или ассоциативность с порядком вычисления. Для данного выражения E1 op E2Надо только, чтобы перед оператором op применяется как E1 а также E2 следует оценить, но между собой, E1 а также E2 можно оценить в любом порядке.

Правила приоритета определяют порядок, в котором применяются операторы, когда в выражении более одного оператора, например E1 op1 E2 op2 E3,

Ассоциативность используется для определения того, какие операнды связываются с каким оператором, когда один и тот же оператор используется более одного раза, то есть в E1 op E2 op E3интерпретируется ли это как (E1 op E2) op E3 или же E1 op (E2 op E3),

2
По вопросам рекламы [email protected]