Главная » Просмотр файлов » B. Stroustrup - The C++ Programming Language

B. Stroustrup - The C++ Programming Language (794319), страница 84

Файл №794319 B. Stroustrup - The C++ Programming Language (B. Stroustrup - The C++ Programming Language) 84 страницаB. Stroustrup - The C++ Programming Language (794319) страница 842019-05-09СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 84)

These T objects may own resources thatthen would be leaked.Section 13.6.1A Simple vector377To handle this problem, we could keep track of which elements have been constructed anddestroy those (and only those) in case of an error:template<class T, class A>vector<T,A>::vector(size_type n, const T& val, const A& a)// elaborate implementation:alloc{a}// copy the allocator{elem = alloc.allocate(n);// get memory for elementsiterator p;try {iterator end = elem+n;for (p=elem; p!=end; ++p)alloc.construct(p,val);last = space = p;}catch (...) {for (iterator q = elem; q!=p; ++q)alloc.destroy(q);alloc.deallocate(elem,n);throw;}// construct element (§34.4)// destroy constructed elements// free memory// rethrow}Note that the declaration of p is outside the try-block; otherwise, we would not be able to access itin both the try-part and the catch-clause.The overhead here is the overhead of the try-block.

In a good C++ implementation, this overhead is negligible compared to the cost of allocating memory and initializing elements. For implementations where entering a try-block incurs a cost, it may be worthwhile to add a test if (n) beforethe try to explicitly handle the (very common) empty vector case.The main part of this constructor is a repeat of the implementation of std::uninitialized_fill():template<class For, class T>void uninitialized_fill(For beg, For end, const T& x){For p;try {for (p=beg; p!=end; ++p)::new(static_cast<void∗>(&∗p)) T(x);}catch (...) {for (For q = beg; q!=p; ++q)(&∗q)−>˜T();throw;}}// construct copy of x in *p (§11.2.4)// destroy element (§11.2.4)// rethrow (§13.5.2.1)The curious construct &∗p takes care of iterators that are not pointers. In that case, we need to takethe address of the element obtained by dereference to get a pointer. Together with the explicitly378Exception HandlingChapter 13global ::new, the explicit cast to void∗ ensures that the standard-library placement function (§17.2.4)is used to invoke the constructor, and not some user-defined operator new() for T∗s.

The calls toalloc.construct() in the vector constructors are simply syntactic sugar for this placement new. Similarly, the alloc.destroy() call simply hides explicit destruction (like (&∗q)−>˜T()). This code is operating at a rather low level where writing truly general code can be difficult.Fortunately, we don’t have to invent or implement uninitialized_fill(), because the standard libraryprovides it (§32.5.6). It is often essential to have initialization operations that either complete successfully, having initialized every element, or fail, leaving no constructed elements behind. Consequently, the standard library provides uninitialized_fill(), uninitialized_fill_n(), and uninitialized_copy()(§32.5.6), which offer the strong guarantee (§13.2).The uninitialized_fill() algorithm does not protect against exceptions thrown by element destructors or iterator operations (§32.5.6).

Doing so would be prohibitively expensive and probablyimpossible.The uninitialized_fill() algorithm can be applied to many kinds of sequences. Consequently, ittakes a forward iterator (§33.1.2) and cannot guarantee to destroy elements in the reverse order oftheir construction.Using uninitialized_fill(), we can simplify our constructor:template<class T, class A>vector<T,A>::vector(size_type n, const T& val, const A& a)// still a bit messy:alloc(a)// copy the allocator{elem = alloc.allocate(n);// get memory for elementstry {uninitialized_fill(elem,elem+n,val); // copy elementsspace = last = elem+n;}catch (...) {alloc.deallocate(elem,n);// free memorythrow;// rethrow}}This is a significant improvement on the first version of this constructor, but the next sectiondemonstrates how to further simplify it.The constructor rethrows a caught exception.

The intent is to make vector transparent to exceptions so that the user can determine the exact cause of a problem. All standard-library containershave this property. Exception transparency is often the best policy for templates and other ‘‘thin’’layers of software.

This is in contrast to major parts of a system (‘‘modules’’) that generally needto take responsibility for all exceptions thrown. That is, the implementer of such a module must beable to list every exception that the module can throw. Achieving this may involve grouping exceptions into hierarchies (§13.5.2) and using catch(...) (§13.5.2.2).13.6.2 Representing Memory ExplicitlyExperience shows that writing correct exception-safe code using explicit try-blocks is more difficultthan most people expect. In fact, it is unnecessarily difficult because there is an alternative: TheSection 13.6.2Representing Memory Explicitly379‘‘Resource Acquisition Is Initialization’’ technique (§13.3) can be used to reduce the amount ofcode that must be written and to make the code more stylized.

In this case, the key resourcerequired by the vector is memory to hold its elements. By providing an auxiliary class to representthe notion of memory used by a vector, we can simplify the code and decrease the chances of accidentally forgetting to release it:template<class T, class A = allocator<T> >struct vector_base {// memor y structure for vectorA alloc;// allocatorT∗ elem;// star t of allocationT∗ space;// end of element sequence, star t of space allocated for possible expansionT∗ last;// end of allocated spacevector_base(const A& a, typename A::size_type n): alloc{a}, elem{alloc.allocate(n)}, space{elem+n}, last{elem+n} { }˜vector_base() { alloc.deallocate(elem,last−elem); }vector_base(const vector_base&) = delete;// no copy operationsvector_base& operator=(const vector_base&) = delete;vector_base(vector_base&&);vector_base& operator=(vector_base&&);// move operations};As long as elem and last are correct, vector_base can be destroyed.

Class vector_base deals withmemory for a type T, not objects of type T. Consequently, a user of vector_base must construct allobjects explicitly in the allocated space and later destroy all constructed objects in a vector_basebefore the vector_base itself is destroyed.The vector_base is designed exclusively to be part of the implementation of vector.

It is alwayshard to predict where and how a class will be used, so I made sure that a vector_base can’t becopied and also that a move of a vector_base properly transfers ownership of the memory allocatedfor elements:template<class T, class A>vector_base<T,A>::vector_base(vector_base&& a): alloc{a.alloc},elem{a.elem},space{a.space},last{a.space}{a.elem = a.space = a.last = nullptr; // no longer owns any memor y}template<class T, class A>vector_base<T,A>::& vector_base<T,A>::operator=(vector_base&& a){swap(∗this,a);return ∗this;}380Exception HandlingChapter 13This definition of the move assignment uses swap() to transfer ownership of any memory allocatedfor elements. There are no objects of type T to destroy: vector_base deals with memory and leavesconcerns about objects of type T to vector.Given vector_base, vector can be defined like this:template<class T, class A = allocator<T> >class vector {vector_base<T,A> vb;void destroy_elements();public:using size_type = unsigned int;// the data is hereexplicit vector(size_type n, const T& val = T(), const A& = A());vector(const vector& a);vector& operator=(const vector& a);// copy constructor// copy assignmentvector(vector&& a);vector& operator=(vector&& a);// move constructor// move assignment˜vector() { destroy_elements(); }size_type size() const { return vb.space−vb.elem; }size_type capacity() const { return vb.last−vb.elem; }void reserve(size_type);// increase capacityvoid resize(size_type, T = {});void clear() { resize(0); }void push_back(const T&);// change the number of elements// make the vector empty// add an element at the end// ...};template<class T, class A>void vector<T,A>::destroy_elements(){for (T∗ p = vb.elem; p!=vb.space; ++p)p−>˜T();// destroy element (§17.2.4)vb.space=vb.elem;}The vector destructor explicitly invokes the T destructor for every element.

This implies that if anelement destructor throws an exception, the vector destruction fails. This can be a disaster if it happens during stack unwinding caused by an exception and terminate() is called (§13.5.2.5). In thecase of normal destruction, throwing an exception from a destructor typically leads to resourceleaks and unpredictable behavior of code relying on reasonable behavior of objects. There is noreally good way to protect against exceptions thrown from destructors, so the library makes noguarantees if an element destructor throws (§13.2).Section 13.6.2Representing Memory Explicitly381Now the constructor can be simply defined:template<class T, class A>vector<T,A>::vector(size_type n, const T& val, const A& a):vb{a,n}// allocate space for n elements{uninitialized_fill(vb.elem,vb.elem+n,val); // make n copies of val}The simplification achieved for this constructor carries over to every vector operation that dealswith initialization or allocation.

For example, the copy constructor differs mostly by using uninitialized_copy() instead of uninitialized_fill():template<class T, class A>vector<T,A>::vector(const vector<T,A>& a):vb{a.alloc,a.size()}{uninitialized_copy(a.begin(),a.end(),vb.elem);}This style of constructor relies on the fundamental language rule that when an exception is thrownfrom a constructor, subobjects (including bases) that have already been completely constructed willbe properly destroyed (§13.3). The uninitialized_fill() algorithm and its cousins (§13.6.1) provide theequivalent guarantee for partially constructed sequences.The move operations are even simpler:template<class T, class A>vector<T,A>::vector(vector&& a):vb{move(a.vb)}// transfer ownership{}// move constructorThe vector_base move constructor will set the argument’s representation to ‘‘empty.’’For the move assignment, we must take care of the old value of the target:template<class T, class A>vector<T,A>::& vector<T,A>::operator=(vector&& a){clear();// destroy elementsswap(∗this,a);// transfer ownership}// move assignmentThe clear() is strictly speaking redundant because I could assume that the rvalue a would bedestroyed immediately after the assignment.

However, I don’t know if some programmer has beenplaying games with std::move().13.6.3 AssignmentAs usual, assignment differs from construction in that an old value must be taken care of. Firstconsider a straightforward implementation:382Exception HandlingChapter 13template<class T, class A>vector<T,A>& vector<T,A>::operator=(const vector& a)// offers the strong guarantee (§13.2){vector_base<T,A> b(alloc,a.size());// get memoryuninitialized_copy(a.begin(),a.end(),b.elem); // copy elementsdestroy_elements();// destroy old elementsswap(vb,b);// transfer ownershipreturn ∗this;// implicitly destroy the old value}This vector assignment provides the strong guarantee, but it repeats a lot of code from constructorsand destructors.

Характеристики

Тип файла
PDF-файл
Размер
18,76 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6458
Авторов
на СтудИзбе
304
Средний доход
с одного платного файла
Обучение Подробнее