[C + + explanation] C + + exception handling | exception specification specifier

Posted by erisande on Sat, 25 Dec 2021 16:30:47 +0100

preface

The noexcept keyword is an exception handling keyword for C + + only.

stay Last In, we learned about exception throwing, catching and overloading. Consider the following questions:

  • If a function (possibly from a third-party library) throws an exception, how do you know the type it may throw?
    Looking at the source code is indeed a way, but what if the function body is long or the function is nested?
    What if the third-party library function has only function declaration and no function implementation?

This brings us to today's topic - exception specification specifier

What is an exception specification?

The exception specification is used to describe the types of exceptions that may be thrown by the function. As a modifier of the function declaration, it follows the parameter list [()] and is consistent with the static function description const 1 Put it together.

grammar

Its standard syntax is:

[adding] ret-type func-name( list ) [adding] throw( exception ) ;

Among them, throw() is preceded by a general function declaration (or implementation). The data type written in throw indicates the exceptions that may be thrown by the function, such as:

void func1() throw();						//Indicates that no exceptions are thrown
void func2() throw(int);					//int type exceptions may be thrown
void func3() throw(const char * , float);	//C-wind string and single precision floating-point exceptions may be thrown
void func4() throw(thread);					//thread object exceptions may be thrown

As you can see, no type is written in throw(), which means that the function does not throw any exceptions.

significance

  1. With exception specifications, when you need to understand function exceptions, you just need to open the declaration at a glance.
  2. Maintainers should not throw any exception types other than specifiers.
  3. The specifier is part of the function interface and is used to explain how to use the function correctly.

Exceptions beyond specifications

Consider the following codes:

void func() throw(int){
	throw 'x';//It does not conform to the abnormal specification
}
int main(){
	try{
		func();
	}
	catch(int e){
		cout<<"exception in int!\n";
	}
	catch(char e){
		cout<<"exception in char!\n";
	}
	return 0;
}

How does the compiler react? The following is a list of reactions that do not match the compiler.

  • BCC:
    Abnormal program termination
    
  • g++:
    terminate called after throwing an instance of 'char'
    
  • VS2019,VC:
    exception in char!
    
  • Most online compilers:
    warning: dynamic exception specifications are deprecated in C++11 [-Wdeprecated]
        3 | void func() throw(int)
          |             ^~~~~
    terminate called after throwing an instance of 'char'
    Aborted (core dumped)
    

It can be seen that except VS and VC, most compilers will directly reject non-standard exception throwing. Because this is the C++11 specification.



noexcept keyword

Note: the noexcept keyword can only be used for C + +.

This keyword is added in C++11 to replace the throw() specifier. Indicates that the function will not throw any exceptions.
Its standard form is:

ret-type func_name( [params] ) [adding...] noexcept( noexcept(exception) )

The () after the first noexcept is a Boolean expression, indicating that the function is noexcept (that is, it is throw()) if and only if the Boolean value is true.
After the first noexcept (...) It can be omitted, which is equivalent to noexcept(true). (indicates that no exception will be thrown at any time)

The second noexcept(...) is similar to a function. Its parameter must be a function execution statement (parenthesis, such as func()), indicating whether to check whether the function throws an exception.
The following function declaration indicates that func() does not throw an exception if and only if funcc() does not throw an exception 2:

void func() noexcept( noexcept(funcc()) );

Abnormal transitivity

Use compilers other than Vc and VS to execute the following programs (because VC and VS do not comply with C++11 exception specification):

#include<iostream>
using namespace std;

void funcc(){
	throw 114514;
}

void func() noexcept//No exception will be thrown
{
	funcc();//Throw an exception in another function
}

int main(){
	try{
		func();
	}
	catch(int err){
		cerr<<"exception!\n";
	}
	return 0;
}
terminate called after throwing an instance of 'int'
Aborted (core dumped)

It is not difficult to see that exceptions are passed. A function is noexcept if and only if its function body, called functions and methods do not throw exceptions. Even if an exception is thrown in the called function, it is not noexcept.
Change the above procedure to:

#include<iostream>
using namespace std;

void funcc(){
	throw 114514;
}

void func() 
/* [-] *///noexcept
/* [+] */  noexcept( noexcept(funcc()) )
{
	funcc();
}

int main(){
	try{
		func();
	}
	catch(int err){
		cerr<<"exception!\n";
	}
	return 0;
}
#(normal operation)
exception!




@Haohaocppdebugger
2021/12/21 

-----THE END-----
THANK YOU !

More articles

  1. Static function description: the modifier before the function body {} (or before the end of the declaration) indicates that the function cannot modify variables. ↩︎

  2. There are two possibilities:
    1.func() calls funcc(), and funcc() may throw exceptions, which is equivalent to a white list of exceptions thrown.
    2.func() function includes (or is included, or is similar to) funcc(). Therefore, as long as funcc() does not make an error, func() must be OK, that is, the two are unrelated functions. ↩︎

Topics: C++ Back-end