Здравствуйте, Went, Вы писали:
W>Здрасте. Стандартизирована ли точка выполнения программы, когда вызовутся деструкторы объектов, созданных в процессе вызова функции. То есть вот: W>Могу ли я быть уверен, что Boo вызовется раньше, чем Foo!!!? Или каждый компилятор свободен в своем выборе?
Да, можешь быть уверен. Временные объекты рушатся в конце т.н. full expression (грубо говоря, там, где стоит ";").
Здравствуйте, Went, Вы писали:
W>Просто я знаю толк в извращениях Представьте себе такую шнягу: "постдеструктор", который должен выполнится автоматом тогда, когда вызван самый верхний конструктор. Долго думал, как это сделать, в конце концов сделал такое:
W>Это фишка работает, но грязно, ибо глючет в случаях вроде: W>
W>add_element(new Derived);
W>
W>Ибо add_element срабатывает раньше postBase. А обидно
Здравствуйте, Went, Вы писали:
W>Просто я знаю толк в извращениях Представьте себе такую шнягу: "постдеструктор", который должен выполнится автоматом тогда, когда вызван самый верхний конструктор. Долго думал, как это сделать, в конце концов сделал такое: W>
Здравствуйте, remark, Вы писали:
R>Так просто ты тут не отделаешься. Тебе надо добавлять дефолтный параметр PostIniter& post_initer = PostIniter() и во все произвольные классы.
Да, но я тут описал сильно упрощенную модель. В реале это немного сложнее и полезнее. Грубо говоря, PostIniter — это семейство классов с разной стратегией инициализации и разнообразными параметрами.
R>Плюс будет плохо работать при исключениях, ибо работа выполняется в деструкторе.
Здравствуйте, Went, Вы писали:
R>>Да, можешь быть уверен. Временные объекты рушатся в конце т.н. full expression (грубо говоря, там, где стоит ";").
W>Спасибо. Хорошо, что стандартизировано, хотя, мне кажется, что было бы логичнее разрушать их по сразу выходу из функции, не дожидаясь конца выражения.
А смысл? Так ими можно воспользоваться несколько раз:
X const& foo(X const& x)
{
cout << x.data++;
return x;
}
int main()
{
foo(foo(foo(X())));
}
Или даже ещё лучше пример будет:
X const& init(X const&)
{
const_cast<X&>(x).data = rand();
}
void foo(X const& x1, X const X2);
int main()
{
foo(init(X()), init(X()));
}
В общем соль в том, что на этот объект могут быть ссылки после вызова функции, даже если он и временный.
Или даже ещё лучше пример:
Здравствуйте, Went, Вы писали:
W>Здравствуйте, remark, Вы писали:
R>>Да, можешь быть уверен. Временные объекты рушатся в конце т.н. full expression (грубо говоря, там, где стоит ";").
W>Спасибо. Хорошо, что стандартизировано, хотя, мне кажется, что было бы логичнее разрушать их по сразу выходу из функции, не дожидаясь конца выражения.
Здравствуйте, _nn_, Вы писали:
__>Вы можете явно указать ваши действия.
Просто я знаю толк в извращениях Представьте себе такую шнягу: "постдеструктор", который должен выполнится автоматом тогда, когда вызван самый верхний конструктор. Долго думал, как это сделать, в конце концов сделал такое:
Здравствуйте, remark, Вы писали:
R>Так просто ты тут не отделаешься. Тебе надо добавлять дефолтный параметр PostIniter& post_initer = PostIniter() и во все произвольные классы.
не надо учить плохому
нельзя передавать временные объекты в функцию (и в конструктор) по неконстантной ссылке
вот такой код не компилируется в comeau
struct B
{
};
struct A
{
A(B& b = B()) // error: initial value of reference to non-const must be an lvalue
{}
};
void g()
{
A a;
}
как я понимаю, неконстантые ссылки на временные объекты поддерживает Visual Studio с включенными расширениями
Здравствуйте, Went, Вы писали:
R>>Так просто ты тут не отделаешься. Тебе надо добавлять дефолтный параметр PostIniter& post_initer = PostIniter() и во все произвольные классы.
W>Да, но я тут описал сильно упрощенную модель. В реале это немного сложнее и полезнее. Грубо говоря, PostIniter — это семейство классов с разной стратегией инициализации и разнообразными параметрами.
Раз в каждый производный класс всё равно добавлять код, можно попробовать явно определять MDT и из него явно вызывать пост-инициализацию. По-краней мере будет стабильно работать с исключениями (и если исключение вылетает во время выполнения конструктора, и если исключение вылетает во время работы пост-инициализации), и в случае, когда объект начинает использоваться до конца full expression.
R>>Плюс будет плохо работать при исключениях, ибо работа выполняется в деструкторе.
W>Да, не учел. Очередная неприятность.
Тут могу только предложить в конструкторе PostIniter ассёртом проверять, что std::uncaught_exception()== false. В деструкторе если std::uncaught_exception()== false, то вызывать пост-инициализацию, в противном случае не вызывать. Тут вроде как получается, что из пост-инициализации можно кидать исключения, не смотря на то, что она делается в деструкторе (хммм... я ничего не упускаю?).
Это несколько сужает область применения, но с практической т.з. вроде незначительно.
Хотя и тут могут быть проблемы, если исключение произошло не в конструкторе, а между завершением конструктора и концом full expression — можем получить объект без пост-инициализации. Что-то типа:
remember(new Derived()), potentially_throws();
Не, всё-таки без явного вызова тут ничего хорошего не получается...
W>А чем? Там явно вызывается init/finit, мне нужен именно неявный вызов.
А там реализуется семантика конструкторов/деструкторов для произвольных функций. Т.е. автоматически вызывается функция из каждого класса в иерархии в порядке от базового к производному или обратно.
Здравствуйте, Went, Вы писали:
W>Да, но я тут описал сильно упрощенную модель. В реале это немного сложнее и полезнее. Грубо говоря, PostIniter — это семейство классов с разной стратегией инициализации и разнообразными параметрами.
Ужос!!! Интересно бы понять, что за выгоды и вкусности такие предоставляет подход, что ты готов мириться с read-only кодом?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Went, Вы писали:
W>Ибо add_element срабатывает раньше postBase. А обидно
А чем не устраивают стандартные подходы к проблеме?
Там фабрики всякие, pimpl и д.р?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, uzhas, Вы писали:
U>нельзя передавать временные объекты в функцию (и в конструктор) по неконстантной ссылке
Зато у временных объектов можно позвать неконтантный метод...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском