[2026] C++ noexcept Complete Guide | Exception Specifications & Move Optimization
이 글의 핵심
Master C++ noexcept: exception specifications, conditional noexcept, move optimization for containers, terminate on violation, and production patterns.
What is noexcept?
noexcept is a C++11 keyword specifying that a function does not throw exceptions. If it throws anyway, std::terminate is called, terminating the program.
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
void func() noexcept {
// Throwing causes std::terminate
}
void func2() noexcept(true) { // Same as noexcept
// ...
}
void func3() noexcept(false) { // May throw
// ...
}
Why needed?:
- Optimization: Compiler can omit stack unwinding code
- STL optimization:
std::vectorchecks noexcept move operators - Clarity: Explicitly states function won’t throw
- Safety: Required for exception-safe guarantees 다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ Without noexcept
class Widget {
public:
Widget(Widget&& other) {
// std::vector uses copy (safe)
}
};
// ✅ With noexcept
class Widget {
public:
Widget(Widget&& other) noexcept {
// std::vector uses move (fast)
}
};
noexcept Behavior
아래 코드는 cpp를 사용한 구현 예제입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
void func() noexcept {
throw std::runtime_error("error"); // Calls std::terminate
}
// Conceptual behavior
void func() {
try {
// Function body
throw std::runtime_error("error");
} catch (...) {
std::terminate(); // All exceptions → terminate
}
}
noexcept vs throw()
| Feature | noexcept (C++11) | throw() (C++98, deprecated) |
|---|---|---|
| On exception | std::terminate | std::unexpected → std::terminate |
| Optimization | ✅ Possible | ❌ Limited |
| Conditional | ✅ Possible | ❌ Not possible |
| Recommended | ✅ Use | ❌ Don’t use |
| 아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요. |
// ❌ throw(): deprecated
void func() throw() {
// ...
}
// ✅ noexcept: recommended
void func() noexcept {
// ...
}
Conditional noexcept
다음은 간단한 cpp 코드 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
template<typename T>
void func(T value) noexcept(noexcept(T(value))) {
T copy(value);
}
Explanation: noexcept(noexcept(T(value))) checks if T’s copy constructor is noexcept. Outer noexcept is the specifier, inner noexcept is the operator returning bool.
Practical Examples
Example 1: Move Operations
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class Buffer {
int* data;
size_t size;
public:
// ✅ noexcept move constructor
Buffer(Buffer&& other) noexcept
: data(other.data), size(other.size) {
other.data = nullptr;
other.size = 0;
}
// ✅ noexcept move assignment
Buffer& operator=(Buffer&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
}
return *this;
}
};
Why noexcept matters: std::vector reallocation uses move if move constructor is noexcept, otherwise uses copy for exception safety. Without noexcept, performance degrades significantly.
Example 2: swap
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class Widget {
public:
void swap(Widget& other) noexcept {
std::swap(data, other.data);
}
private:
int data;
};
// std::swap specialization
namespace std {
template<>
void swap(Widget& a, Widget& b) noexcept {
a.swap(b);
}
}
Example 3: Destructor
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// Destructors are implicitly noexcept
class MyClass {
public:
~MyClass() noexcept { // Explicit (optional)
// Throwing causes std::terminate
}
};
Key: Destructors are implicitly noexcept unless explicitly specified noexcept(false) (not recommended).
Example 4: Conditional noexcept
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
template<typename T>
class Container {
public:
void push_back(T&& value)
noexcept(noexcept(data.push_back(std::move(value)))) {
data.push_back(std::move(value));
}
private:
std::vector<T> data;
};
Explanation: push_back is noexcept only if vector::push_back is noexcept. This propagates nothrow guarantee from member operations.
noexcept Operator
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// noexcept(expression): returns bool at compile time
void func() noexcept {}
void func2() {}
static_assert(noexcept(func())); // true
static_assert(!noexcept(func2())); // false
// Use in conditional noexcept
template<typename T>
void wrapper(T value) noexcept(noexcept(T(value))) {
T copy(value);
}
Key: noexcept(expr) is a compile-time operator returning bool. Used in conditional noexcept specifications.
Common Issues
Issue 1: Throwing in noexcept
아래 코드는 cpp를 사용한 구현 예제입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ Throws in noexcept
void func() noexcept {
throw std::runtime_error("error"); // std::terminate
}
// ✅ try-catch
void func() noexcept {
try {
riskyOperation();
} catch (...) {
// Handle exception
}
}
Issue 2: std::vector Optimization
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class Widget {
public:
// ❌ Without noexcept
Widget(Widget&&) {
// vector reallocation uses copy
}
// ✅ With noexcept
Widget(Widget&&) noexcept {
// vector reallocation uses move
}
};
Impact: Without noexcept, std::vector copies elements on reallocation instead of moving them, causing significant performance degradation for large objects.
Issue 3: Conditional noexcept
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
template<typename T>
class Wrapper {
public:
// noexcept only if T's move constructor is noexcept
Wrapper(Wrapper&& other)
noexcept(std::is_nothrow_move_constructible_v<T>)
: value(std::move(other.value)) {}
private:
T value;
};
Issue 4: Destructor
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// Destructor is implicitly noexcept
class MyClass {
public:
~MyClass() {
// Throwing causes std::terminate
}
};
// Explicit noexcept(false) (not recommended)
class Bad {
public:
~Bad() noexcept(false) {
throw std::runtime_error("error");
}
};
Key: Never throw from destructors. During stack unwinding, a second exception causes terminate.
Optimization
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// noexcept enables optimization
void func() noexcept {
// Compiler can omit stack unwinding code
}
// std::vector
std::vector<Widget> vec;
vec.push_back(Widget()); // Uses move if noexcept
Performance impact: noexcept allows compiler to generate simpler, faster code by omitting exception handling machinery.
Production Patterns
Pattern 1: RAII Wrapper
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class FileHandle {
FILE* file_;
public:
FileHandle(const char* path) : file_(fopen(path, "r")) {
if (!file_) {
throw std::runtime_error("Failed to open file");
}
}
// noexcept destructor
~FileHandle() noexcept {
if (file_) {
fclose(file_); // Doesn't throw
}
}
// noexcept move
FileHandle(FileHandle&& other) noexcept
: file_(other.file_) {
other.file_ = nullptr;
}
// Prohibit copy
FileHandle(const FileHandle&) = delete;
};
Pattern 2: Exception-Safe swap
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class Buffer {
std::vector<char> data_;
public:
// noexcept swap
void swap(Buffer& other) noexcept {
data_.swap(other.data_); // vector::swap is noexcept
}
friend void swap(Buffer& a, Buffer& b) noexcept {
a.swap(b);
}
};
// Usage
Buffer b1, b2;
swap(b1, b2); // Guaranteed no exceptions
Pattern 3: Conditional noexcept Template
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
template<typename T>
class Wrapper {
T value_;
public:
// noexcept if T's move constructor is noexcept
Wrapper(Wrapper&& other)
noexcept(std::is_nothrow_move_constructible_v<T>)
: value_(std::move(other.value_)) {}
// noexcept if T's swap is noexcept
void swap(Wrapper& other)
noexcept(noexcept(std::swap(value_, other.value_))) {
using std::swap;
swap(value_, other.value_);
}
};
// Usage
Wrapper<std::string> w1, w2;
static_assert(noexcept(w1.swap(w2))); // string::swap is noexcept
FAQ
Q1: When to use noexcept?
A:
- Move operations: Move constructor, move assignment operator
- swap: Swap functions
- Destructor: Always noexcept (implicit)
- Exception-free functions: Functions that don’t throw 아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
class MyClass {
public:
MyClass(MyClass&&) noexcept; // Move constructor
MyClass& operator=(MyClass&&) noexcept; // Move assignment
void swap(MyClass&) noexcept; // swap
~MyClass() noexcept; // Destructor (implicit)
};
Q2: Performance benefits of noexcept?
A:
- Optimization: Compiler omits stack unwinding code
- STL optimization:
std::vectoruses noexcept move operations 다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class Widget {
public:
// ❌ Without noexcept
Widget(Widget&& other) {
// std::vector uses copy (safe but slow)
}
};
std::vector<Widget> vec;
vec.reserve(100); // Reallocation uses copy
class Widget {
public:
// ✅ With noexcept
Widget(Widget&& other) noexcept {
// std::vector uses move (fast)
}
};
std::vector<Widget> vec;
vec.reserve(100); // Reallocation uses move
Q3: What happens on noexcept violation?
A: std::terminate is called, terminating the program.
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
void func() noexcept {
throw std::runtime_error("error"); // std::terminate
}
int main() {
func(); // Program terminates
}
Q4: How to use conditional noexcept?
A: Use noexcept(condition). If condition is true, function is noexcept; if false, may throw. 아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
template<typename T>
void func(T value) noexcept(noexcept(T(value))) {
T copy(value); // noexcept if T's copy constructor is noexcept
}
// Or use type_traits
template<typename T>
void func2(T value) noexcept(std::is_nothrow_copy_constructible_v<T>) {
T copy(value);
}
Q5: Are destructors always noexcept?
A: Yes, by default. Unless explicitly specified noexcept(false) (not recommended).
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class MyClass {
public:
~MyClass() { // Implicitly noexcept
// Throwing causes std::terminate
}
};
// Explicit noexcept(false) (not recommended)
class Bad {
public:
~Bad() noexcept(false) {
throw std::runtime_error("error");
}
};
Q6: What is the noexcept operator?
A: An operator that checks if an expression is noexcept at compile time, returning bool. 아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
void func() noexcept {}
void func2() {}
static_assert(noexcept(func())); // true
static_assert(!noexcept(func2())); // false
// Use in conditional noexcept
template<typename T>
void wrapper(T value) noexcept(noexcept(T(value))) {
T copy(value);
}
Q7: Is noexcept part of function type?
A: Yes, since C++17. Before C++17, it wasn’t. 아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// C++17:
void (*ptr1)() noexcept = func; // OK
void (*ptr2)() = func; // Error (type mismatch)
// Function pointer types differ
using FuncNoexcept = void(*)() noexcept;
using Func = void(*)();
Q8: Learning resources for noexcept?
A:
- “Effective Modern C++” by Scott Meyers (Item 14)
- “C++ Concurrency in Action” by Anthony Williams
- cppreference.com - noexcept
Why noexcept Matters for Move Operations
Vector Reallocation Example
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <vector>
#include <iostream>
class Slow {
std::vector<int> data_;
public:
// ❌ Without noexcept
Slow(Slow&& other) { data_ = std::move(other.data_); }
};
class Fast {
std::vector<int> data_;
public:
// ✅ With noexcept
Fast(Fast&& other) noexcept { data_ = std::move(other.data_); }
};
int main() {
std::vector<Slow> slowVec;
slowVec.reserve(10);
for (int i = 0; i < 100; ++i) {
slowVec.push_back(Slow{}); // Reallocation uses copy!
}
std::vector<Fast> fastVec;
fastVec.reserve(10);
for (int i = 0; i < 100; ++i) {
fastVec.push_back(Fast{}); // Reallocation uses move
}
}
Performance difference: For large objects, noexcept move can be 10-100x faster than copy during reallocation.
Best Practices
1. Always noexcept for Move Operations
Move constructors and move assignment operators should almost always be noexcept. 아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
class MyClass {
public:
MyClass(MyClass&&) noexcept;
MyClass& operator=(MyClass&&) noexcept;
};
2. Always noexcept for swap
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
void swap(MyClass& a, MyClass& b) noexcept {
using std::swap;
swap(a.member1, b.member1);
swap(a.member2, b.member2);
}
3. Destructors Are Implicitly noexcept
Don’t throw from destructors. If you must handle errors, catch and log them. 아래 코드는 cpp를 사용한 구현 예제입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
~MyClass() noexcept {
try {
cleanup();
} catch (...) {
// Log error but don't rethrow
}
}
4. Use Conditional noexcept for Templates
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
template<typename T>
class Wrapper {
public:
Wrapper(Wrapper&& other)
noexcept(std::is_nothrow_move_constructible_v<T>)
: value_(std::move(other.value_)) {}
private:
T value_;
};
5. Don’t Overuse noexcept
Only mark functions noexcept if you’re certain they won’t throw. Violations cause terminate, which is worse than an exception.
Production Patterns
Pattern 1: RAII Resource Guard
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <cstdio>
#include <stdexcept>
class FileHandle {
FILE* file_;
public:
FileHandle(const char* path) : file_(fopen(path, "r")) {
if (!file_) {
throw std::runtime_error("Failed to open file");
}
}
~FileHandle() noexcept {
if (file_) {
fclose(file_); // Doesn't throw
}
}
FileHandle(FileHandle&& other) noexcept
: file_(other.file_) {
other.file_ = nullptr;
}
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
};
Pattern 2: Exception-Safe Swap
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <vector>
class Buffer {
std::vector<char> data_;
public:
void swap(Buffer& other) noexcept {
data_.swap(other.data_); // vector::swap is noexcept
}
friend void swap(Buffer& a, Buffer& b) noexcept {
a.swap(b);
}
};
// Usage
Buffer b1, b2;
swap(b1, b2); // Guaranteed no exceptions
Pattern 3: Conditional noexcept Template
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <type_traits>
#include <utility>
template<typename T>
class Wrapper {
T value_;
public:
// noexcept if T's move constructor is noexcept
Wrapper(Wrapper&& other)
noexcept(std::is_nothrow_move_constructible_v<T>)
: value_(std::move(other.value_)) {}
// noexcept if T's swap is noexcept
void swap(Wrapper& other)
noexcept(noexcept(std::swap(value_, other.value_))) {
using std::swap;
swap(value_, other.value_);
}
};
// Usage
Wrapper<std::string> w1, w2;
static_assert(noexcept(w1.swap(w2))); // string::swap is noexcept
Summary
Key Points
- noexcept: Specifies function doesn’t throw exceptions
- Optimization: Enables compiler optimizations and container move operations
- Move operations: Should almost always be noexcept for performance
- Conditional: Use
noexcept(noexcept(expr))to propagate nothrow guarantee - Violation: Causes
std::terminate, so only use when certain
When to Use noexcept
| Operation | Recommendation | Reason |
|---|---|---|
| Move constructor | ✅ Always | Container optimization |
| Move assignment | ✅ Always | Container optimization |
| Destructor | ✅ Implicit | Stack unwinding safety |
| swap | ✅ Always | Exception safety |
| Regular functions | ⚠️ Carefully | Only if truly nothrow |
noexcept Checklist
- Move constructor marked noexcept?
- Move assignment marked noexcept?
- swap function marked noexcept?
- Destructor doesn’t throw?
- Conditional noexcept for templates?
- Function truly doesn’t throw?
Related Articles
- C++ noexcept Specifier Guide
- C++ Exception Performance
- C++ noexcept Complete Guide | Exception Contracts, Move Optimization, Production Patterns [#42-1]
Keywords
C++ noexcept, exception specifications, move optimization, std::terminate, conditional noexcept, container performance One-line summary: noexcept specifies functions that don’t throw exceptions, enabling compiler optimizations and container move operations. Essential for move constructors and swap functions.