Попробуйте переписать unitialized_fill() (параграф 19.4.4, параграф E3.1) так, что бы он справлялся с деструкторами, генерирующими исключения. Возможно ли это? Если да, то какова стоимость такого решения? Если нет, то почему?
От тот код что в книге:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include <iostream> using std::cout; using std::endl; #include <vector> using std::vector; template<class For, class T> void uninitialized_fill(For beg, For end, T& x) { For p; try { for(p=beg;p!=end;++p) new (static_cast<void*>(&*p))T(x);//создаем копию х в *p (параграф 10.4.11) //&*p мы получаем адресс разыменованого элемента с целью получения указателя. } catch(...) { for(For q=beg;q!=p;++q)(&*q)->~T();//вызываем деструктор throw; } } int main() { vector<int> v(4,10); int val(4); uninitialized_fill<vector<int>::iterator,int>(v.begin(),v.end(),val); for(int i=0;i<v.size();i++) cout <<v[i]<<' '; cout <<endl; return 0; } |
Тут как то память выделяется фиг что разберешь. Ладно подумаем что произойдет если у нас будет исключение в деструкторе. Да допустим у нас вылетело исключение в деструкторе и мы уже не сможем поудалаять остальные объекты, у нас получиться часть объектов удалилась а часть осталась.
Мы можем минимизировать утечку ресурсов сделав так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
template<class For, class T> void uninitialized_fill(For beg, For end, T& x) { For p; try { for(p=beg;p!=end;++p) new (static_cast<void*>(&*p))T(x);//создаем копию х в *p (параграф 10.4.11) //&*p мы получаем адресс разыменованого элемента с целью получения указателя. } catch(...) { for(For q=beg;q!=p;++q) { try { (&*q)->~T();//вызываем деструктор } catch(...) { } } throw; } } |
Вообще здесь нифига не понятно что происходит например для int явно видимо деструктор нельзя вызвать ну либо я вызываю, но что то эффекта не наблюдаю вот примерчик с исключением, ну ладно в любом случае проедим эту тему.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
#include <iostream> using std::cout; using std::endl; #include <vector> using std::vector; class ex{}; template<class For, class T> void uninitialized_fill(For beg, For end, T& x) { For p; try { int count(0); for(p=beg;p!=end;++p) { cout <<"mu tyt 1"<<endl; if(count==2)throw 1; new (static_cast<void*>(&*p))T(x);//создаем копию х в *p (параграф 10.4.11) count++; } //&*p мы получаем адресс разыменованого элемента с целью получения указателя. } catch(...) { cout <<"mu tyt"<<endl; for(For q=beg;q!=p;++q) { cout <<"one"<<endl; /*try {*/ (&*q)->~T();//вызываем деструктор /*} catch(...) { }*/ } // throw; } } int main() { vector<int> v(4,10); int val(4); uninitialized_fill<vector<int>::iterator,int>(v.begin(),v.end(),val); for(int i=0;i<v.size();i++) cout <<v[i]<<' '; cout <<endl; return 0; } |
[youtube]https://www.youtube.com/watch?v=aQzdv_Kfp58[/youtube]