[2026] C++ Exception Specifications: noexcept, History, and throw() Removal
이 글의 핵심
C++ exception specifications from throw() to noexcept: move operations, swap, destructors, conditional noexcept, and why dynamic specs were removed.
Introduction
Exception specifications describe what exceptions a function may throw.
1. History of exception specifications
C++03 — throw()
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// No exceptions
void func() throw();
// Specific types
void func() throw(std::exception);
void func() throw(int, double);
// Removed in C++17
C++11 — noexcept
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// No exceptions
void func() noexcept;
// Conditional
void func() noexcept(true); // noexcept
void func() noexcept(false); // may throw
2. noexcept basics
Basic usage
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 비동기 처리를 통해 효율적으로 작업을 수행합니다, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
void safe_func() noexcept {
std::cout << "no throw" << std::endl;
}
void risky_func() {
throw std::runtime_error("error");
}
int main() {
safe_func();
try {
risky_func();
} catch (const std::exception& e) {
std::cout << e.what() << std::endl;
}
return 0;
}
Checking noexcept
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
#include <type_traits>
void func1() noexcept {}
void func2() {}
int main() {
std::cout << std::boolalpha;
std::cout << "func1: " << noexcept(func1()) << std::endl; // true
std::cout << "func2: " << noexcept(func2()) << std::endl; // false
return 0;
}
3. Move operations and noexcept
Move constructor
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <vector>
#include <iostream>
class Widget {
public:
Widget() = default;
Widget(Widget&& other) noexcept
: data(std::move(other.data)) {
std::cout << "move ctor" << std::endl;
}
Widget(const Widget& other)
: data(other.data) {
std::cout << "copy ctor" << std::endl;
}
private:
std::vector<int> data{1, 2, 3};
};
int main() {
std::vector<Widget> vec;
vec.reserve(10);
Widget w;
vec.push_back(std::move(w)); // move ctor (noexcept)
return 0;
}
Important: std::vector often requires noexcept move constructors to move elements during reallocation.
4. swap and noexcept
swap implementation
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class Data {
public:
Data(int v) : value(v) {}
void swap(Data& other) noexcept {
std::swap(value, other.value);
}
int getValue() const noexcept { return value; }
private:
int value;
};
namespace std {
template<>
void swap(Data& lhs, Data& rhs) noexcept {
lhs.swap(rhs);
}
}
int main() {
Data d1(10), d2(20);
std::swap(d1, d2);
std::cout << d1.getValue() << std::endl; // 20
std::cout << d2.getValue() << std::endl; // 10
return 0;
}
5. Conditional noexcept
Templates and noexcept
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
template<typename T>
class Container {
public:
Container(Container&& other)
noexcept(std::is_nothrow_move_constructible_v<T>)
: data(std::move(other.data)) {}
void clear() noexcept(std::is_nothrow_destructible_v<T>) {
data.clear();
}
private:
std::vector<T> data;
};
6. Destructors and noexcept
Implicit noexcept
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class MyClass {
public:
// destructor implicitly noexcept unless a member’s dtor can throw
~MyClass() {
// throwing here -> std::terminate during stack unwind
}
};
class Explicit {
public:
~Explicit() noexcept {
// still must not throw
}
};
Exceptions in destructor cleanup
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 비동기 처리를 통해 효율적으로 작업을 수행합니다, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class SafeClass {
public:
~SafeClass() noexcept {
try {
cleanup();
} catch (const std::exception& e) {
std::cerr << "cleanup error: " << e.what() << std::endl;
}
}
private:
void cleanup() {
// may throw
}
};
7. Practical example: resource management
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
#include <memory>
class Resource {
public:
Resource() {
std::cout << "allocate" << std::endl;
}
~Resource() noexcept {
std::cout << "release" << std::endl;
}
void use() noexcept {
std::cout << "use" << std::endl;
}
};
class Manager {
public:
Manager() : res(std::make_unique<Resource>()) {}
Manager(Manager&& other) noexcept
: res(std::move(other.res)) {}
Manager& operator=(Manager&& other) noexcept {
res = std::move(other.res);
return *this;
}
void process() noexcept {
if (res) {
res->use();
}
}
private:
std::unique_ptr<Resource> res;
};
int main() {
Manager m1;
m1.process();
Manager m2 = std::move(m1);
m2.process();
return 0;
}
Summary
Key points
- noexcept: C++11 exception contract
- throw(): deprecated (removed in C++17)
- Move operations: mark noexcept when safe
- Destructors: implicitly noexcept in normal cases
- Conditional:
noexcept(expression)
When to use noexcept
| Function | noexcept? | Reason |
|---|---|---|
| Move ctor | Yes | Container performance |
| Move assign | Yes | Container performance |
| swap | Yes | Exception safety |
| Destructor | Yes (default) | Avoid terminate during unwind |
| Simple getters | Often | No throws |
| Complex logic | Maybe not | May throw |