Open In App

Noexcept Specifier in C++17

Last Updated : 22 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

In C++ programming, error handling and exception safety are critical elements of writing sturdy and dependable code. The noexcept specifier is a feature delivered in C++11 and, in addition, more suitable in C++17 that facilitates developers control over exceptions and enhances the predictability of their packages.

What is Noexcept Specifier?

The noexcept specifier is used to signify that a function will not throw any exceptions. This record is valuable for both compilers and programmers. By asserting that a function is noexcept, you provide the compiler with the assurance that no exceptions will propagate from that function, permitting it to optimize code and generate more efficient binaries. Moreover, other developers working with our code will recognize that a noexcept function is safe to call in scenarios where exceptions need to be prevented.

Syntax of Noexcept Specifier

The noexcept specifier can be applied to function declarations, function definitions, and even lambda expressions.

void myFunction() noexcept {
// Function implementation
}

Examples of Noexcept Specifier

1. Preventing Exceptions

In this example, we will create a function to calculate the factorial of a non-negative integer.

C++




// C++ Program to implement
// Preventing Exceptions
#include <iostream>
#include <stdexcept>
  
using namespace std;
  
// Function to calculate factorial
// of non negative integer
unsigned long long calfact(unsigned int num) noexcept
{
    // Initialize the result to 1
    unsigned long long result = 1;
    for (unsigned int i = num; i >= 1; i--) {
        // Multiply the end result via
        // the current value of i
        result = result * i;
    }
  
    // Return the result to main function
    return result;
}
  
int main()
{
    try {
        unsigned int num;
        cout << "Enter a non negative integer: ";
  
        // Take the input from user
        cin >> num;
  
        // Initialize the result of calfact
        // function to fact variable
        unsigned long long fact = calfact(num);
  
        // Print the output
        cout << "Factorial of " << num << " is: " << fact
             << endl;
    }
    catch (const std::exception& e) {
        // Print exception message
        // if occured
        cerr << "error: " << e.what() << endl;
    }
  
    return 0;
}


Output:

Enter a non negative integer: 6
Factorial of 6 is: 720

Explanation of the above method:

In this example, we calculated the factorial of a non-negative integer entered through the user. This code uses the calfact() function, marked with noexcept to assure that it does not throw any exceptions. In this program we have used two C++ libraries: iostream for input and output operations and stdexcept for managing exceptions. The calfact() function calculates the factorial of a non-negative integer. It takes an integer num as an enter parameter and returns an integer as the end result.

2. Enhancing Debugging

When debugging our code, it may be useful to perceive functions that are explicitly marked as noexcept to make sure that exceptions aren’t silently swallowed. This makes it less difficult to track down sudden exceptions in our codebase.

In this example, we will create a function that handles division by zero using noexcept.

C++




// C++ Program to implement
// Enhancing Debugging
#include <iostream>
#include <stdexcept>
  
using namespace std;
  
// Function to perform division of two
// integer and with handle division by zero
int Division(int num, int den) noexcept
{
    if (den == 0) {
        // Print error message if den is zero
        std::cerr << "Error: Division by zero detected!"
                  << std::endl;
        return 0; // Return 0 as a result of division by
                  // zero
    }
    int result = num / den;
  
    // Return the result to main function
    return result;
}
  
// Main function
int main()
{
    try {
        int num, den;
        cout << "Enter two integers: ";
  
        // Take two integers from user
        cin >> num >> den;
  
        // call the function and store the result
        int result = Division(num, den);
  
        // Print the result
        cout << "Result of division:" << result << endl;
    }
    catch (const std::exception& e) {
  
        // Print exception message
        // if occured
        cerr << "An exception occurred: " << e.what()
             << endl;
    }
    return 0;
}


Output 1:

Enter two integers: 12 2
Result of division is: 6

Output 2 (Division by 0):

Enter two integers: 7 0
Error: Division by zero detected!
Result of division is: 0

Explanation of the Above Program:

The Division function handles the case of division by 0 by printing an errors message to the standard error stream (std::cerr). The main function demonstrates each scenarios: a hit division by using a non-zero number and division via zero. The noexcept specifier ensures that exceptions are not silently stuck, improving debugging through the way of permitting us to handle unique errors in the function.

Advantages of Using Noexcept

  • Performance Optimization: function marked as noexcept permit the compiler to perform optimizations which could lead to stepped forward performance. When the compiler knows that a function will not throw exceptions, it may take away certain runtime tests and streamline code execution.
  • Predictable behavior: via putting forward that a function does no longer throw exceptions, you offer a clean contract to the users of the function. This makes the behavior of the function extra predictable and helps developers write more strong code.
  • Compile-Time Optimizations: The noexcept specifier can permit the compiler to carry out diverse compile-time optimizations. As an instance, the compiler is probably capable of cast off positive exception-related bookkeeping, ensuing in smaller and faster binaries.
  • Ease of renovation: The use of noexcept could make your codebase simpler to maintain. While a function is marked as noexcept, it communicates to different developers that the function is designed to handle exceptional cases within itself and will not propagate exceptions. This may cause cleaner and greater self-contained error-handling with code.
  • Compile-Time errors Detection: If a noexcept function attempts to throw an exception or calls another function which can throw exceptions, the compiler will generate an error. This will assist seize potential issues early in the improvement technique, preventing runtime surprises related to exceptions.
  • Higher error handling: Whilst designing error-handling strategies, we may depend on function marked as noexcept to keep away from situations in which sudden exceptions may disrupt the go with the flow of your program.
  • Interface readability: By way of marking functions with noexcept, we’re successfully documenting the anticipated behavior of these function. This could help improve the clarity of our code’s interface and make it less difficult for different developers to understand the way to use our function correctly.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads