Здравствуйте, Karamat, Вы писали:
K>там все гораздо хуже
K>K>в функции используется АПИ, требующее ссылок типа std::vector<MyClass1*>
Можно:
а) поменять API на
some_extern_api(std::vector<MyClass1> const&)
б) сделать
std::transform(vector_of_values, vector_of_pointers, std::addressof)
PM>>Используйте value типы, там где это возможно, обычно это упрощает код
K>Там по настоящему более общая задача — в функции надо гарантированно выполнить определенные действия, даже если возникнет исключение. Поэтому не важно, указатель или value. Для такого придумали finally, а в С++, на мой взгляд, минимальный оверхед будет при таком коде:
K>K>void FunA(int a, int b, int c)
K>{
K> try
K> {
K> //код функции
K> }
K> catch(...)
K> {
K> FunAFinally(a, b, c);
K> throw;
K> }
K> FunAFinally(a, b, c);
K>}
K>void FunAFinally(int a, int b, int c)
K>{
K> //код финализатора
K>}
K>
В языке для этого есть RAII, finally это где-то там, за углом, в Java мире.
Чтобы уменьшить синтаксический оверхед от одноразовых RAII, лет 10 назад добавили
Boost.ScopeExit. В C++11 это делается лямбдой, т.е. чисто языковыми средствами.
В последнее время это развивается в scope(exit), scope(failure):
*
http://habrahabr.ru/post/270545/
*
Другой взгляд на исключения
Здравствуйте, Karamat, Вы писали:
K>при генерации исключения надо прибить все объекты, которые накопились в коллекциях
K>есть ли возможность это сделать без десятков строк идиотского кода ?
А так?
class MyFun
{
public:
MyFun();
~MyFun(); // гарантировано вызовется
void operator () () // а то и просто метод MyFun::run()
{
// дальше идет тяжелая работа с коллекциями, где создаются и добавляются в эти коллекции экземпляры
// MyClass1..MyClassN, при этом в любой момент может выскочить исключение
}
private:
std::vector<MyClass1*> v1;
std::list<MyClass2*> v2;
...
std::map<MyClassN*, MyClassN1*> vN;
};
{ MyFun myFun; myFun(); }
Не так уж и много дополнительного кода... Плюс в качестве бонуса появляется возможность легко разбивать логику на отдельные методы.