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

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

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

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

What we would like is a recognizable mechanism forchecking assertions. What follows here is a (possibly slightly overelaborate) mechanism forexpressing a variety of assertions and a variety of responses to failures. First, I define mechanismsfor deciding when to test and deciding what to do if an assertion fails:namespace Assert {enum class Mode { throw_, terminate_, ignore_ };constexpr Mode current_mode = CURRENT_MODE;constexpr int current_level = CURRENT_LEVEL;constexpr int default_level = 1;constexpr bool level(int n){ return n<=current_level; }struct Error : runtime_error {Error(const string& p) :runtime_error(p) {}};// ...}The idea is to test whenever an assertion has a ‘‘level’’ lower than or equal to current_level.

If anassertion fails, current_mode is used to choose among three alternatives. The current_level and current_mode are constants because the idea is to generate no code whatsoever for an assertion unlesswe have made a decision to do so. Imagine CURRENT_MODE and CURRENT_LEVEL to be set in thebuild environment for a program, possibly as compiler options.The programmer will use Assert::dynamic() to make assertions:namespace Assert {// ...string compose(const char∗ file, int line, const string& message)// compose message including file name and line number{ostringstream os ("(");os << file << "," << line << "):" << message;return os.str();}362Exception HandlingChapter 13template<bool condition =level(default_level), class Except = Error>void dynamic(bool assertion, const string& message ="Assert::dynamic failed"){if (assertion)return;if (current_mode == Assert_mode::throw_)throw Except{message};if (current_mode == Assert_mode::terminate_)std::terminate();}template<>void dynamic<false,Error>(bool, const string&){}// do nothingvoid dynamic(bool b, const string& s){dynamic<true,Error>(b,s);}// default actionvoid dynamic(bool b){dynamic<true,Error>(b);}// default message}I chose the name Assert::dynamic (meaning ‘‘evaluate at run time’’) to contrast with static_assert(meaning ‘‘evaluate at compile time’’; §2.4.3.3).Further implementation trickery could be used to minimize the amount of code generated.Alternatively, we could do more of the testing at run time if more flexibility is needed.

This Assertis not part of the standard and is presented primarily as an illustration of the problems and theimplementation techniques. I suspect that the demands on an assertion mechanism vary too muchfor a single one to be used everywhere.We can use Assert::dynamic like this:void f(int n)// n should be in [1:max){Assert::dynamic<Assert::level(2),Assert::Error>((n<=0 || max<n), Assert::compose(__FILE__,__LINE__,"range problem");// ...}The __FILE__ and __LINE__ are macros that expand at their point of appearance in the source code(§12.6.2).

I can’t hide them from the user’s view by placing them inside the implementation ofAssert where they belong.Assert::Error is the default exception, so we need not mention it explicitly. Similarly, if we arewilling to use the default assertion level, we don’t need to mention the level explicitly:Section 13.4Enforcing Invariants363void f(int n)// n should be in [1:max){Assert::dynamic((n<=0 || max<n),Assert::compose(__FILE__,__LINE__,"range problem");// ...}I do not recommend obsessing about the amount of text needed to express an assertion, but byusing a namespace directive (§14.2.3) and the default message, we can get to a minimum:void f(int n)// n should be in [1:max){dynamic(n<=0||max<n);// ...}It is possible to control the testing done and the response to testing through build options (e.g., controlling conditional compilation) and/or through options in the program code. That way, you canhave a debug version of a system that tests extensively and enters the debugger and a productionversion that does hardly any testing.I personally favor leaving at least some tests in the final (shipping) version of a program.

Forexample, with Assert the obvious convention is that assertions marked as level zero will always bechecked. We never find the last bug in a large program under continuous development and maintenance. Also, even if all else works perfectly, having a few ‘‘sanity checks’’ left to deal with hardware failures can be wise.Only the builder of the final complete system can decide whether a failure is acceptable or not.The writer of a library or reusable component usually does not have the luxury of terminatingunconditionally.

I interpret that to mean that for general library code, reporting an error – preferably by throwing an exception – is essential.As usual, destructors should not throw, so don’t use a throwing Assert() in a destructor.13.5 Throwing and Catching ExceptionsThis section presents exceptions from a language-technical point of view.13.5.1 Throwing ExceptionsWe can throw an exception of any type that can be copied or moved. For example:class No_copy {No_copy(const No_copy&) = delete;};class My_error {// ...};// prohibit copying (§17.6.4)364Exception Handlingvoid f(int n){switch (n) {case 0: throw My_error{};case 1: throw No_copy{};case 2: throw My_error;}}Chapter 13// OK// error : can’t copy a No_copy// error : My_error is a type, rather than an objectThe exception object caught (§13.5.2) is in principle a copy of the one thrown (though an optimizeris allowed to minimize copying); that is, a throw x; initializes a temporary variable of x’s type withx.

This temporary may be further copied several times before it is caught: the exception is passed(back) from called function to calling function until a suitable handler is found. The type of theexception is used to select a handler in the catch-clause of some try-block. The data in the exception object – if any – is typically used to produce error messages or to help recovery. The processof passing the exception ‘‘up the stack’’ from the point of throw to a handler is called stack unwinding.

In each scope exited, the destructors are invoked so that every fully constructed object is properly destroyed. For example:void f(){string name {"Byron"};try {string s = "in";g();}catch (My_error) {// ...}}void g(){string s = "excess";{string s = "or";h();}}void h(){string s = "not";throw My_error{};string s2 = "at all";}After the throw in h(), all the strings that were constructed are destroyed in the reverse order of theirconstruction: "not", "or", "excess", "in", but not "at all", which the thread of control never reached,and not "Byron", which was unaffected.Section 13.5.1Throwing Exceptions365Because an exception is potentially copied several times before it is caught, we don’t usuallyput huge amounts of data in it. Exceptions containing a few words are very common.

The semantics of exception propagation are those of initialization, so objects of types with move semantics(e.g., strings) are not expensive to throw. Some of the most common exceptions carry no information; the name of the type is sufficient to report the error. For example:struct Some_error { };void fct(){// ...if (something_wrong)throw Some_error{};}There is a small standard-library hierarchy of exception types (§13.5.2) that can be used eitherdirectly or as base classes.

For example:struct My_error2 : std::runtime_error {const char∗ what() const noexcept { return "My_error2"; }};The standard-library exception classes, such as runtime_error and out_of_range, take a string argument as a constructor argument and have a virtual function what() that will regurgitate that string.For example:void g(int n)// throw some exception{if (n)throw std::runtime_error{"I give up!"};elsethrow My_error2{};}void f(int n)// see what exception g() throws{try {void g(n);}catch (std::exception& e) {cerr << e.what() << '\n';}}13.5.1.1 noexcept FunctionsSome functions don’t throw exceptions and some really shouldn’t.

To indicate that, we can declaresuch a function noexcept. For example:double compute(double) noexcept; // may not throw an exception366Exception HandlingChapter 13Now no exception will come out of compute().Declaring a function noexcept can be most valuable for a programmer reasoning about a program and for a compiler optimizing a program. The programmer need not worry about providingtry-clauses (for dealing with failures in a noexcept function) and an optimizer need not worry aboutcontrol paths from exception handling.However, noexcept is not completely checked by the compiler and linker.

What happens if theprogrammer ‘‘lied’’ so that a noexcept function deliberately or accidentally threw an exception thatwasn’t caught before leaving the noexcept function? Consider:double compute(double x) noexcept;{string s = "Courtney and Anya";vector<double> tmp(10);// ...}The vector constructor may fail to acquire memory for its ten doubles and throw a std::bad_alloc.

Inthat case, the program terminates. It terminates unconditionally by invoking std::terminate()(§30.4.1.3). It does not invoke destructors from calling functions. It is implementation-definedwhether destructors from scopes between the throw and the noexcept (e.g., for s in compute()) areinvoked. The program is just about to terminate, so we should not depend on any object anyway.By adding a noexcept specifier, we indicate that our code was not written to cope with a throw.13.5.1.2 The noexcept OperatorIt is possible to declare a function to be conditionally noexcept. For example:template<typename T>void my_fct(T& x) noexcept(Is_pod<T>());The noexcept(Is_pod<T>()) means that My_fct may not throw if the predicate Is_pod<T>() is true butmay throw if it is false.

I may want to write this if my_fct() copies its argument. I know that copying a POD does not throw, whereas other types (e.g., a string or a vector) may.The predicate in a noexcept() specification must be a constant expression. Plain noexcept meansnoexcept(true).The standard library provides many type predicates that can be useful for expressing the conditions under which a function may throw an exception (§35.4).What if the predicate we want to use isn’t easily expressed using type predicates only? Forexample, what if the critical operation that may or may not throw is a function call f(x)? The noexcept() operator takes an expression as its argument and returns true if the compiler ‘‘knows’’ that itcannot throw and false otherwise.

For example:template<typename T>void call_f(vector<T>& v) noexcept(noexcept(f(v[0])){for (auto x : v)f(x);}Section 13.5.1.2The noexcept Operator367The double mention of noexcept looks a bit odd, but noexcept is not a common operator.The operand of noexcept() is not evaluated, so in the example we do not get a run-time error ifwe pass call_f() with an empty vector.A noexcept(expr) operator does not go to heroic lengths to determine whether expr can throw; itsimply looks at every operation in expr and if they all have noexcept specifications that evaluate totrue, it returns true. A noexcept(expr) does not look inside definitions of operations used in expr.Conditional noexcept specifications and the noexcept() operator are common and important instandard-library operations that apply to containers.

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

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

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

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