C++ 2: boost::bind & boost::function

340 views
222 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
340
On SlideShare
0
From Embeds
0
Number of Embeds
31
Actions
Shares
0
Downloads
7
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

C++ 2: boost::bind & boost::function

  1. 1. Лекция 6. Исключения Valery Lesin. C++ In-Depth, 2014 1
  2. 2. Способы обработки ошибок • Ошибка повод для std::terminate • Вернуть признак ошибки и выставить глобальный код ошибки • Вернуть код ошибки • Бросить исключение: – его невозможно проигнорировать; – распространяется автоматически; – выносит обработку из основного потока выполнения – незаменимо в конструкторах или операторах. Valery Lesin. C++ In-Depth, 2014 2
  3. 3. try...catch Valery Lesin. C++ In-Depth, 2014 3 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. try { // throws explicit or implicit throw exception_type(/*...*/); //... } catch(std::exception const& err) {/*...*/} catch(...) { /*...*/ throw; } //... Type::Type(/*...*/) try : field1_(/*...*/) , field2_(/*...*/) { /*...*/ } catch(std::exception const&) { /*some logging*/ throw; }
  4. 4. Типы исключений • Исключение может быть любым типом (хоть int или const char*) • Разумно делать класс исключения, наследуя его от std::exception (и реализовать what) • Есть стандартные исключения, например, std::runtime_error, logic_error (<stdexcept>) • Перерехват по – точному соответствию типа; – ссылке на базовый класс; – по приводимому указателю. Valery Lesin. C++ In-Depth, 2014 4
  5. 5. Использование RAII • Есть ли проблемы в этом коде? Valery Lesin. C++ In-Depth, 2014 5 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. double sqrt(double value) { if (value < 0) throw runtime_error("nagative"); /*...*/ } double* make_roots(double* values, size_t size) { double* roots = new double[size]; transform(values, values + size, roots, sqrt); return roots; }
  6. 6. Использование RAII (2) • Есть ли проблемы в этом коде? Valery Lesin. C++ In-Depth, 2014 6 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. double* make_roots(double* values, size_t size) { double* roots = new double[size]; try { transform(values, values + size, roots, sqrt); } catch(std::exception const& err) { delete [] roots; cerr << err.what() << endl; throw; } return roots; } double* make_roots(double* values, size_t size) { unique_ptr<double> roots(new double[size]); transform(values, values + size, roots.get(), sqrt); return roots.release(); }
  7. 7. Передача параметров • Исправляет ли вызов в (10) ошибочный вызов в (3)? Valery Lesin. C++ In-Depth, 2014 7 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. void foo(T* a, U* b); /*...*/ void foo(new T(/*...*/), new U(/*...*/)); typedef shared_ptr<T> T_ptr; typedef shared_ptr<U> U_ptr; void foo(T_ptr a, U_ptr b); /*...*/ void foo(T_ptr(new T(/*...*/)), U_ptr(new U(/*...*/)));
  8. 8. Передача параметров(2) • Если для соответствующего RAII класса нет фабрики, используйте способ (1). Valery Lesin. C++ In-Depth, 2014 8 1. 2. 3. 4. 5. 6. 7. 8. 9. void foo(T_ptr a, U_ptr b); //(1) T_ptr a(new T(/*...*/)); U_ptr b(new U(/*...*/)); foo(a, b); // (2) foo(make_shared<T>(/*...*/), make_shared<U>(/*...*/));
  9. 9. Класс stack • Попробуем разработать безопасную реализацию класса stack Valery Lesin. C++ In-Depth, 2014 9 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. template<class T> struct stack { stack(size_t def_size = 10); ~stack(); T pop(); void push(T const&); /*...*/ private: size_t size_; // buffer size size_t used_; // number of objects T* buf_ ; // main buffer };
  10. 10. Класс stack, конструктор • Такой код нейтрален – любое исключение передается дальше. • Не вызывает утечек памяти. • Независимо от наличия исключений стек остается согласованным (либо несозданным). Valery Lesin. C++ In-Depth, 2014 10 1. 2. 3. 4. 5. 6. template<class T> stack<T>::stack(size_t def_size) : size_(def_size) , used_(0) , buf_ (new T[def_size]) {}
  11. 11. Гарантии безопасности исключений • Базовая гарантия: даже при наличии генерируемых объектом класса T (или иных) исключений утечки в классе stack отсутствуют (согласованность). • Строгая гарантия: если операция прекращается из-за генерации исключения, состояние программы остается неизменным (rollback). • Гарантия отсутствия исключений: функция не генерирует исключений ни при каких обстоятельствах. Valery Lesin. C++ In-Depth, 2014 11
  12. 12. Гарантия отсутствия исключений • Деструкторы: Что будет, если 13-й объект при создании бросит исключение, а затем 12-й при удалении? • Функция swap Valery Lesin. C++ In-Depth, 2014 12 1. Type array [42];
  13. 13. Копирование стека • Воспользуемся вспомогательной функцией: Valery Lesin. C++ In-Depth, 2014 13 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 18. 19. template<class T> T* new_copy(const T* src, size_t src_size, size_t dst_size) { // could be made via unique_ptr T* dst = new T[dst_size]; try { copy(src, src + src_size, dst); } catch(...) { delete[] dst; throw; } return dst; }
  14. 14. Копирование стека (2) Valery Lesin. C++ In-Depth, 2014 14 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 18. 19. 20. 21. 22. template<class T> stack<T>::stack(stack const& o) : buf_ (new_copy(o.buf_, o.src_size, o.dst_size)) , size_(o.size_) , used_(o.used_) { } template<class T> stack<T>& stack<T>::operator=(stack<T> const& o) { if (this != other) { T* cp = new_copy(o.buf_, o.src_size, o.dst_size); delete[] buf_; // no more exceptions buf_ = cp; size_ = o.size_; used_ = o.used_; } return *this; }
  15. 15. push / pop Valery Lesin. C++ In-Depth, 2014 15 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. template<class T> void stack<T>::push(T const& t) { if (used_ == size_) { size_t sz = 2 * size_ + 1; T* cp = new_copy(buf_, size_, sz); delete [] buf_; // now ok buf_ = cp; size_ = sz; } buf_[used_] = t; ++used_; } template<class T> T stack<T>::pop() { if (empty()) throw /*...*/; T res = buf[used_ - 1]; --used_; return res; // what to do? }
  16. 16. pop / top Valery Lesin. C++ In-Depth, 2014 16 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. template<class T> T& stack<T>::top() { if (empty()) throw /*...*/; return buf[used_ - 1]; } template<class T> void stack<T>::pop() { if (empty()) throw /*...*/; --used_; } • Разделим pop на pop и top:
  17. 17. Гарантии и требования stack • Требования: – наличие конструктора по умолчанию; – наличие копирующего конструктора; – деструктор без исключений; – безопасный оператор присваивания. • Гарантии: – строгая гарантия при удовлетворении требований. Valery Lesin. C++ In-Depth, 2014 17
  18. 18. Уменьшение требований stack • Для начала рассмотрим функции: Valery Lesin. C++ In-Depth, 2014 18 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. template<class T1, class T2> void construct(T1* p, T2 const& value) { new (p) T1(value); } template<class T> void destroy(T* p) { p->~T();} template<class fwd_it> void destroy(fwd_it beg, fwd_it end) { while (beg != end) { destroy(&*beg); ++beg; } }
  19. 19. stack_impl Valery Lesin. C++ In-Depth, 2014 19 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. stack_impl::stack_impl(size_t size) : buf (static_cast<T*>(size == 0 ? 0 : new char[size * sizeof(T)]) , size(size) , used(0) {} stack_impl::~stack_impl() { destroy(buf, buf + used); delete static_cast<void*>(buf); } • Сделаем вспомогательный класс:
  20. 20. Новый вариант stack Valery Lesin. C++ In-Depth, 2014 20 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. struct stack { /**/ stack_impl impl_; } stack::stack(size_t def_size) : impl_(def_size) {} stack::stack(stack const& o) : impl_(o.impl_.used) { while (used < o.impl_.used) { construct(impl_.buf + impl_.used, o.impl_.buf + impl_.used); ++impl_.used; } } stack& stack::operator=(stack o) { swap(*this, o); return *this; }
  21. 21. To be continued… Valery Lesin. C++ In-Depth, 2014 21

×