Exceptions can be caught either by reference or by value in the catch block. Choosing between catching by reference or by value affects how exceptions are handled and has implications for performance and exception object behavior.
Catching Exceptions by Reference
Catching an exception by reference (catch(ExceptionType& e)) is the most common and recommended approach. When you catch by reference:
- No Copying: The exception object is not copied; instead, a reference to the original exception object is used. This is more efficient because it avoids the overhead of creating a new copy.
- Polymorphism Support: Catching by reference allows the use of polymorphism. If the exception type is part of an inheritance hierarchy, catching by reference enables catching derived exceptions using a reference to the base class.
- Modifications: You can modify the exception object within the
catch block if needed.
Example:
try {
throw std::runtime_error("An error occurred");
} catch (std::exception& e) {
std::cerr << "Caught exception: " << e.what() << std::endl;
}
Catching Exceptions by Value
Catching an exception by value (catch(ExceptionType e)) creates a copy of the thrown exception object:
- Copy Overhead: There is additional overhead due to copying the exception object, which can be costly if the exception is complex.
- No Polymorphism: When caught by value, polymorphic behavior is lost because slicing occurs, meaning derived class-specific information is discarded if the exception is part of an inheritance hierarchy.
- Use Case: Catching by value is rarely used and is typically discouraged unless there is a specific need to work with a copy.
Example:
try {
throw std::runtime_error("An error occurred");
} catch (std::exception e) {
std::cerr << "Caught exception by value: " << e.what() << std::endl;
}
Catching by const Reference
Catching exceptions by const reference (catch(const ExceptionType& e)) is also common:
- Immutable Handling: This ensures the exception object cannot be modified inside the
catch block.
- Efficiency and Safety: Provides the benefits of catching by reference while ensuring the original exception is not changed.
Example:
try {
throw std::runtime_error("An error occurred");
} catch (const std::exception& e) {
std::cerr << "Caught exception: " << e.what() << std::endl;
}
Summary
- By Reference: Recommended for efficiency and polymorphism support.
- By Value: Avoid due to performance overhead and loss of polymorphism.
- By
const Reference: Ideal for read-only access to the exception.