Это правильное поведение? - PullRequest
0 голосов
/ 14 февраля 2019
class foo {
    std::vector<int> datas;
public:
    template <typename It>
    foo(It x, It y) {
        for(; x != y; ++x)
            insert(*x);
    }

    void insert(int val) {
        if(val == 5)
            throw 99;
        else
            datas.push_back(val);
    }

    void print() const {
        for(int x : datas)
            std::cout << x << " ";
    }
};

int main() {
    std::vector<int> v{1, 2, 3, 5, 6, 7};
    foo* f;
    try {
        f = new foo(std::begin(v), std::end(v));
    }catch(int const& x) {
    }
    f->print();
}

Я полагаю, что f не будет построен в этом случае;исключение, генерируемое методом вставки, не обрабатывается в теле конструктора foo.Я получил следующий вывод на GCC 8.2.0: 1 2 3 5 6 7

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

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

Хотя у меня нет доказательств, я считаю, что это интересное следствиеоптимизаций компилятора и рассуждения кода.Мы видим, что результат равен 1 2 3 5 6 7, хотя в коде есть оператор throw для элемента 5.Как это могло бы произойти?

На мой взгляд, поскольку у нас f->print() вне блока try, компилятор считает, что f никогда не инициализируется - поэтому конструктор никогда не генерирует.Поскольку конструктор никогда не выбрасывает, val == 5 никогда не верна!Из-за этого ветка удаляется.И, таким образом, у нас есть результат, который у нас есть.

0 голосов
/ 15 февраля 2019

Я полагаю, что f не будет создан в этом случае;

В этом случае не будет создан экземпляр foo.

Кроме того, f не был бы назначен, поэтому его значение останется неопределенным.

Это правильное поведение?

Доступ к объекту путем косвенного обращения через неопределенный указатель имеетнеопределенное поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...