По словам опытного автора из сообщества C ++, приведенный ниже код не должен компилироваться. Он не прав? - PullRequest
1 голос
/ 03 декабря 2011

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

Навстречу морали

Кстати,это также означает, что единственное (только повторное) возможное использование для конструктора function-try-block - это преобразование исключения, выданного из подобъекта base или member.Это Мораль № 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;
}

Ответы [ 3 ]

2 голосов
/ 03 декабря 2011

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

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

1 голос
/ 03 декабря 2011

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

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

0 голосов
/ 03 декабря 2011

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

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