Согласно знающему автору в сообществе C ++, код, указанный ниже, не должен компилировать. Он неправ?

StackOverflow https://stackoverflow.com/questions/8367459

Вопрос

По словам Херб Саттер, код ниже не будет компилироваться. Смотрите этот сайт http://www.gotw.ca/gotw/066.htm откуда я извлек следующий текст, относительно function-try-blocks :

К какой -то морали

Между прочим, это также означает, что единственным (только повторяющимся) возможным использованием для блок-блока конструктора является перевод исключения, выброшенного из базового или члена Subobject. Это моральный #1. Далее, Мораль №2 говорит, что депутатор-функциональные блюки совершенно используют ...

"--Но ждать!" Я слышал, как кто -то прерывается из середины комнаты. «Я не согласен с моральным #1. Я могу придумать другое возможное использование для конструкторов-функциональных блоков, а именно для свободных ресурсов, выделенных в списке инициализаторов или в теле конструктора!»

Извините, нет. В конце концов, помните, что, как только вы попадете в обработчик своего конструктора Try-Block, любые локальные переменные в органе конструктора также уже выходят из области, и вам гарантировано, что базовые субобъекты или объекты-члены больше не существуют, периода. Вы даже не можете ссылаться на их имена. Либо части вашего объекта никогда не были построены, либо те, которые были построены, уже были уничтожены. Таким образом, вы не можете очистить все, что полагается на ссылку на базу или члена класса (и, в любом случае, это то, для чего нужны базовые и деструкторы -члены, верно?).

Предполагая эту цитату, следующий код не должен компилировать, как объект cat уже был разрушен к тому времени, когда процесс попадает в catch пункт. Но это так, по крайней мере, с VSC2008.

class Cat
{
    public:
    Cat() { cout << "Cat()" << endl; }
    ~Cat() { cout << "~Cat()" << endl; }
};

class Dog
{
    public:
    Dog() { cout << "Dog()" << endl; throw 1; }
    ~Dog() { cout << "~Dog()" << endl; }
};


class UseResources
{
    class Cat *cat;
    class Dog dog;

    public:
    UseResources();
    ~UseResources() { delete cat; cat = NULL; cout << "~UseResources()" << endl; }
};

UseResources::UseResources() try : cat(new Cat), dog() { cout << "UseResources()" << endl; } catch(...)
{
    delete cat;
    throw;
}
Это было полезно?

Решение

Я не думаю, что Херб Саттер на самом деле говорит, что он не составит. Он просто объясняет последствия того, что стандарт говорит о ситуации (15.3.10):

Ссылаясь на любой нестатический элемент или базовый класс объекта в обработчике для блока функции конструктора или деструктора для этого объекта приводит к неопределенное поведение.

Другие советы

Предполагая эту цитату, следующий код не должен компилировать ...

Ну, он не сказал, что они никогда не будут компилировать. Во всяком случае, я интерпретировал цитату как «делать это не определено». Неопределенное поведение разрешено иметь какой -либо результат - вплоть до успешного компиляции, и впоследствии делать удивительные вещи.

Компиляторы отличаются, а также есть переключатели, которые определяют, насколько компилятор будет строгим с кодом, который он компилирует. Этот код, безусловно, вызовет ошибки (разломы SEG и т. Д.). Попробуйте, чтобы все переключатели компилятора заставили его найти это.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top