C++的前世今生-C++11
C++98(ISO/IEC 14882:1998)
C++98 是 C++ 的第一个标准化版本(ISO/IEC 14882:1998),它正式确立了 C++ 的核心语言特性和标准库。以下是 C++98 的主要特性总结:
一、核心语言特性**
- 模板(Templates)
- 支持函数模板和类模板,实现泛型编程。
- 例如:
std::vector
、std::sort
等标准库组件依赖模板。
- 标准模板库(STL)
- 包含容器(如
vector
、list
、map
)、迭代器(iterators)和算法(如sort
、find
)。 - 基于泛型编程思想,强调“数据与算法分离”。
- 包含容器(如
- 异常处理(Exception Handling)
- 引入
try
、catch
、throw
机制,支持错误处理的标准化。
- 引入
- 命名空间(Namespaces)
- 避免命名冲突,例如
std
是标准库的命名空间。
- 避免命名冲突,例如
- RTTI(运行时类型识别)
- 支持
typeid
和dynamic_cast
,允许在运行时检查类型。
- 支持
- bool 类型
- 引入
bool
关键字(true
/false
),取代传统的int
表示布尔值。
- 引入
- mutable 关键字
- 允许在
const
成员函数中修改被标记为mutable
的成员变量。
- 允许在
- 显式类型转换
- 提供
static_cast
、dynamic_cast
、const_cast
、reinterpret_cast
,替代 C 风格的强制转换。
- 提供
- 默认参数和函数重载
- 支持函数参数的默认值和函数重载(相同函数名,不同参数列表)。
二、标准库组件
- 容器(Containers)
- 序列容器:
vector
、deque
、list
- 关联容器:
set
、map
、multiset
、multimap
- 适配器:
stack
、queue
、priority_queue
- 序列容器:
- 迭代器(Iterators)
- 提供统一的遍历容器元素的接口(如
begin()
、end()
)。
- 提供统一的遍历容器元素的接口(如
- 算法(Algorithms)
- 如
sort()
、find()
、copy()
等,通过迭代器操作容器。
- 如
- 字符串类(std::string)
- 提供安全的字符串操作,替代 C 风格字符数组。
- 输入/输出流(I/O Streams)
iostream
(如cin
、cout
)、fstream
(文件操作)、sstream
(字符串流)。
- 数值处理
定义数值类型的极值,
提供数学函数。
三、其他重要特性
- 局部对象析构顺序
- 局部对象的析构顺序与构造顺序相反(RAII 基础)。
- 运算符重载
- 允许自定义运算符行为(如
+
、<<
)。
- 允许自定义运算符行为(如
- 友元(friend)
- 允许非成员函数或类访问私有成员。
- 静态成员
- 类的静态成员变量和函数。
C++03(ISO/IEC 14882:2003)
C++03(ISO/IEC 14882:2003)是 C++98 的一个技术修正版本(Technical Corrigendum),主要修复了标准中的缺陷和模糊表述,并未引入显著的新特性。它通常被视为 C++98 的“bug fix”版本,核心特性和语法与 C++98 完全一致。以下是 C++03 的细节说明:
一、C++03 的核心变化
- 标准文本修正
- 修复了 C++98 标准中的语法歧义和未定义行为的表述。
- 例如:模板解析规则、模板友元声明的语法等细节更明确。
- 标准库的兼容性改进
- 修正了 STL 中部分容器的接口行为(如
std::vector
的成员函数异常安全性)。 - 明确
std::basic_string
的存储连续性(C++03 保证&s[0]
是连续内存)。
- 修正了 STL 中部分容器的接口行为(如
- 数值限制的扩展
- 在 `` 中增加了对
long long
和unsigned long long
的支持(尽管这些类型在 C++11 才正式成为关键字)。
- 在 `` 中增加了对
二、与 C++98 的兼容性
- 语法完全兼容:所有 C++98 代码在 C++03 中无需修改即可编译。
- 编译器支持:主流编译器(如 GCC、MSVC)通常将 C++98 和 C++03 视为同一版本实现。
三、为什么需要 C++03?
C++98 标准中存在一些未明确的边界情况,例如:
- 模板中嵌套依赖名称的解析规则(需用
typename
消除歧义)。 - 局部模板特化的合法性(C++03 明确禁止)。
这些修正提高了代码的可移植性和一致性。
C++11(ISO/IEC 14882:2011)
C++11(ISO/IEC 14882:2011)是 C++ 的一次重大更新,引入了许多革命性特性,显著提升了代码的简洁性、安全性和性能。以下是 C++11 的核心特性分类总结:
一、核心语言特性
-
自动类型推导(
auto
)-
编译器自动推断变量类型,简化代码:
auto x = 5; // int auto str = "hello"; // const char*
-
-
范围
for
循环-
简化容器遍历:
std::vector<int> v = {1, 2, 3}; for (auto& num : v) { std::cout << num; }
-
-
右值引用与移动语义(
&&
)-
避免深拷贝,提升性能:
std::vector<std::string> v; v.push_back(std::move(str)); // 移动而非拷贝
-
-
Lambda 表达式
-
匿名函数,支持闭包:
auto add = [](int a, int b) { return a + b; }; std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
-
-
nullptr
关键字-
替代
NULL
,明确表示空指针:int* p = nullptr;
-
-
强类型枚举(
enum class
)-
避免命名冲突,限制作用域:
enum class Color { Red, Green }; Color c = Color::Red; // 必须带作用域
-
-
constexpr
常量表达式-
编译时计算:
constexpr int square(int x) { return x * x; } int arr[square(3)]; // 编译期确定数组大小
-
-
委托构造函数
-
构造函数调用其他构造函数:
class A { public:A() : A(0) {} // 委托给 A(int)A(int x) { /*...*/ } };
-
-
override
和final
-
显式标记虚函数重写或禁止继承:
class B final {}; // 禁止继承 virtual void foo() override; // 确保重写基类虚函数
-
二、标准库增强
-
智能指针
-
自动内存管理:
std::unique_ptr<int> ptr(new int(10)); // 独占所有权 std::shared_ptr<int> sptr = std::make_shared<int>(20); // 共享所有权
-
-
std::thread
多线程支持-
原生多线程库:
std::thread t([]() { std::cout << "Hello from thread!"; }); t.join();
-
-
哈希表容器
-
新增无序关联容器:
std::unordered_map<std::string, int> hash_map;
-
-
std::function
和std::bind
-
通用函数包装器:
std::function<int(int, int)> func = std::plus<int>(); std::bind(func, 1, std::placeholders::_1)(2); // 绑定参数
-
-
正则表达式(``)
-
支持正则操作:
std::regex pattern("\\d+"); bool match = std::regex_search("123", pattern);
-
-
元组(
std::tuple
)-
多类型值集合:
auto t = std::make_tuple(1, "hello", 3.14);
-
三、其他重要特性
-
变长模板(Variadic Templates)
-
支持任意数量模板参数:
template<typename... Args> void log(Args... args) { /*...*/ }
-
-
列表初始化(Uniform Initialization)
-
统一初始化语法:
std::vector<int> v{1, 2, 3}; // 替代旧式括号初始化
-
-
static_assert
编译时断言-
编译期条件检查:
static_assert(sizeof(int) == 4, "int must be 4 bytes");
-
-
noexcept
异常规范-
标记函数不抛异常:
void foo() noexcept { /*...*/ }
-
C++14(ISO/IEC 14882:2014)
C++14(ISO/IEC 14882:2014)是 C++11 的小幅改进版本,主要目标是完善 C++11 的特性并修复一些缺陷,而非引入重大变革。以下是 C++14 的核心特性分类总结:
一、核心语言改进
-
泛型 Lambda 表达式
-
Lambda 参数支持
auto
,实现真正的泛型:auto lambda = [](auto x, auto y) { return x + y; }; std::cout << lambda(1, 2.5); // 混合类型参数
-
-
constexpr
函数扩展-
允许
constexpr
函数包含局部变量、循环和简单分支:constexpr int factorial(int n) {int result = 1;for (int i = 1; i <= n; ++i) result *= i;return result; } int arr[factorial(5)]; // 编译期计算 120
-
-
变量模板(Variable Templates)
-
模板可以定义变量而不仅是类型或函数:
template<typename T> constexpr T pi = T(3.1415926535897932385); std::cout << pi<double>; // 输出 double 精度的 π
-
-
二进制字面量
-
直接使用二进制数:
int mask = 0b110101; // 十进制 53
-
-
数字分隔符(Digit Separators)
-
提高长数字可读性:
int million = 1'000'000; double pi = 3.141'592'6535;
-
-
函数返回类型推导(
auto
返回类型)-
省略尾置返回类型(C++11 需要
-> decltype(...)
):auto add(int a, int b) { return a + b; } // 自动推导为 int
-
-
[[deprecated]]
属性-
标记过时代码,编译时警告:
[[deprecated("Use new_func() instead")]] void old_func() {}
-
二、标准库增强
-
std::make_unique
-
补充 C++11 的
std::make_shared
,为unique_ptr
提供工厂函数:auto ptr = std::make_unique<int>(42); // 替代 new
-
-
标准库的
constexpr
支持- 部分标准库函数(如
std::array
、std::tuple
的部分操作)可在编译期使用。
- 部分标准库函数(如
-
std::integer_sequence
-
编译时整数序列,用于元编程:
template<typename T, T... Ints> void print_sequence(std::integer_sequence<T, Ints...>) {((std::cout << Ints << ' '), ...); // C++17 折叠表达式 } print_sequence(std::index_sequence<1, 2, 3>{}); // 输出: 1 2 3
-
-
std::exchange
-
原子性地替换对象值并返回旧值:
int x = 1; int old = std::exchange(x, 42); // x=42, old=1
-
-
std::quoted
-
方便处理带引号的字符串(如 CSV 文件):
std::cout << std::quoted("Hello"); // 输出: "Hello"
-
三、其他改进
-
聚合成员初始化扩展
-
允许聚合类(无自定义构造函数的类)使用默认初始化:
struct Point { int x; int y; }; Point p{1}; // y 初始化为 0(C++11 需完整初始化)
-
-
Lambda 捕获表达式的改进
-
支持在捕获列表中直接初始化变量:
auto lambda = [value = 42]() { return value; };
-
-
sizeof
运算符的扩展-
可直接用于成员变量(无需实例化对象):
struct S { int x; double y; }; size_t sz = sizeof(S::x); // 等价于 sizeof(int)
-
C++17(ISO/IEC 14882:2020)
C++17(ISO/IEC 14882:2017)是 C++14 的增量升级版本,虽然没有 C++11 或 C++20 那样的革命性变化,但引入了许多实用特性,进一步简化代码并提升性能。以下是 C++17 的核心特性分类总结:
一、核心语言特性
-
结构化绑定(Structured Bindings)
-
解构元组、结构体或数组为独立变量:
std::pair<int, std::string> p{42, "hello"}; auto [num, str] = p; // num=42, str="hello"
-
-
if
和switch
的初始化语句-
在条件语句中定义局部变量:
if (auto it = map.find(key); it != map.end()) {// 使用 it } // it 作用域仅限于 if 块
-
-
constexpr if
-
编译期条件分支,简化模板元编程:
template <typename T> auto get_value(T t) {if constexpr (std::is_pointer_v<T>) return *t;else return t; }
-
-
内联变量(Inline Variables)
-
允许头文件中定义
inline
变量,避免多重定义错误:// header.h inline int global_value = 42; // 多个 cpp 包含时不会链接错误
-
-
折叠表达式(Fold Expressions)
-
简化可变参数模板的展开:
template <typename... Args> auto sum(Args... args) { return (... + args); } // args1 + args2 + ...
-
-
auto
模板参数-
非类型模板参数支持
auto
:template <auto value> void print() { std::cout << value; } print<42>(); // 输出 42
-
-
std::byte
-
明确表示字节的类型(替代
char
或unsigned char
):std::byte b{0xFF};
-
-
构造函数模板推导(CTAD)
-
省略模板参数,自动推导容器类型:
std::pair p(1, "hello"); // 自动推导为 std::pair<int, const char*> std::vector v{1, 2, 3}; // 推导为 std::vector<int>
-
二、标准库增强
-
std::optional
-
表示可选值,避免使用
nullptr
或特殊值:std::optional<int> maybe_num = std::nullopt; if (maybe_num) std::cout << *maybe_num;
-
-
std::variant
-
类型安全的联合体(替代
union
):std::variant<int, std::string> v = "hello"; std::cout << std::get<std::string>(v); // 输出 hello
-
-
std::any
-
存储任意类型:
std::any a = 42; std::cout << std::any_cast<int>(a); // 输出 42
-
-
std::string_view
-
非拥有的字符串视图,避免拷贝:
std::string s = "hello"; std::string_view sv = s.substr(0, 3); // "hel"(不拷贝数据)
-
-
std::filesystem
-
文件系统操作(跨平台路径处理):
namespace fs = std::filesystem; fs::path p = "dir/file.txt"; if (fs::exists(p)) std::cout << p.filename(); // "file.txt"
-
-
并行算法(Parallel Algorithms)
-
标准库算法支持并行执行:
std::vector<int> v = {...}; std::sort(std::execution::par, v.begin(), v.end()); // 并行排序
-
-
std::invoke
和std::apply
-
统一调用函数和展开元组参数:
auto func = [](int a, int b) { return a + b; }; std::tuple args{1, 2}; std::cout << std::apply(func, args); // 输出 3
-
三、其他改进
-
嵌套命名空间定义简化
-
简化嵌套命名空间的语法:
namespace A::B::C { } // 替代 namespace A { namespace B { namespace C {} } }
-
-
__has_include
预处理表达式-
检测头文件是否可用:
#if __has_include(<optional>)#include <optional> #endif
-
-
[[fallthrough]]
属性-
明确标记
switch
中的穿透(fallthrough)行为:switch (x) {case 1: do_something(); [[fallthrough]]; // 明确告知编译器case 2: break; }
-
-
[[nodiscard]]
属性-
强制检查函数返回值(避免忽略错误):
[[nodiscard]] int compute_important_value(); compute_important_value(); // 编译器警告:未使用返回值
-
C++20(ISO/IEC 14882:2020)**
C++20(ISO/IEC 14882:2020)是继 C++17 之后的重大更新,引入了许多革命性特性,显著提升了代码的表达能力、性能和安全性。以下是 C++20 的核心特性分类总结:
一、核心语言特性
-
概念(Concepts)
-
对模板参数进行约束,提升错误信息可读性:
template <typename T> concept Addable = requires(T a, T b) { a + b; }; // 要求类型支持 + 操作template <Addable T> T sum(T a, T b) { return a + b; } // 仅接受满足 Addable 的类型
-
-
模块(Modules)
-
替代头文件(
#include
),加快编译速度:// math.ixx (模块接口文件) export module math; export int add(int a, int b) { return a + b; }// main.cpp import math; int main() { return add(1, 2); }
-
-
协程(Coroutines)
-
支持挂起/恢复的函数,简化异步代码:
generator<int> range(int start, int end) {for (int i = start; i < end; ++i)co_yield i; // 挂起并返回值 } for (int i : range(1, 5)) { /*...*/ } // 输出 1, 2, 3, 4
-
-
三路比较(
<=>
,Spaceship Operator)-
简化比较运算符定义:
struct Point {int x, y;auto operator<=>(const Point&) const = default; // 自动生成 ==, !=, <, > 等 };
-
-
范围
for
循环的初始化语句-
允许在范围
for
中定义局部变量:for (auto vec = get_vector(); auto& x : vec) { /*...*/ }
-
-
constexpr
进一步扩展-
支持
virtual
函数、try-catch
、动态内存分配等:constexpr int safe_divide(int a, int b) {if (b == 0) throw "Division by zero"; // 编译期异常return a / b; }
-
-
consteval
立即函数-
强制函数在编译期执行:
consteval int square(int x) { return x * x; } int arr[square(3)]; // 必须编译期计算
-
-
[[no_unique_address]]
属性-
优化空类型成员的内存占用:
struct Empty {}; struct S {[[no_unique_address]] Empty e; // 可能不占额外内存int x; };
-
二、标准库增强
-
范围库(Ranges)
-
提供管道式操作(
|
),简化容器处理:#include <ranges> std::vector<int> v = {1, 2, 3, 4, 5}; auto even = v | std::views::filter([](int x) { return x % 2 == 0; }); for (int i : even) { /*...*/ } // 输出 2, 4
-
-
std::format
格式化库-
类型安全的字符串格式化(类似 Python):
#include <format> std::string s = std::format("Hello, {}! The answer is {:.2f}.", "world", 3.14159);
-
-
std::span
-
轻量级非拥有视图,替代原始指针 + 长度:
void print(std::span<int> s) {for (int x : s) std::cout << x << " "; } std::vector<int> v = {1, 2, 3}; print(v); // 自动转换
-
-
std::jthread
-
自动合并(join)的线程,避免资源泄漏:
std::jthread t([]() { std::cout << "Thread running"; }); // 析构时自动 join
-
-
std::atomic_ref
-
对非原子变量的原子操作:
int x = 0; std::atomic_ref<int> atomic_x(x); atomic_x.fetch_add(1); // 原子操作
-
-
日历和时区支持(`` 扩展)
-
处理日期和时间:
auto now = std::chrono::system_clock::now(); auto today = std::chrono::floor<std::chrono::days>(now); std::cout << std::format("Today is {:%F}", today); // 输出 YYYY-MM-DD
-
三、其他重要特性
-
constinit
关键字-
确保全局变量静态初始化:
constinit static int x = 42; // 必须编译期初始化
-
-
位操作库(``)
-
提供位运算工具:
if (std::has_single_bit(8)) { /* 检查是否为 2 的幂 */ }
-
-
std::source_location
-
替代
__LINE__
和__FILE__
,获取代码位置:void log(std::source_location loc = std::source_location::current()) {std::cout << loc.file_name() << ":" << loc.line(); }
-
-
协程标准库支持
- 提供
std::coroutine_handle
和std::suspend_always
等基础设施。
- 提供
C++23(ISO/IEC 14882:2023)
C++23(ISO/IEC 14882:2023)是 C++20 之后的增量更新版本,虽然不如 C++20 那样引入大量革命性特性,但仍包含许多实用改进,进一步简化代码、增强表达能力和性能。以下是 C++23 的核心特性分类总结:
一、核心语言特性
-
#elifdef
和#elifndef
-
简化条件编译的语法,与
#ifdef
/#ifndef
风格一致:#ifdef FEATURE_A// ... #elifdef FEATURE_B // 替代 #elif defined(FEATURE_B)// ... #endif
-
-
auto(x)
和auto{x}
(显式复制构造)-
强制复制对象并保留类型推导:
std::vector<int> v1 = {1, 2, 3}; auto v2 = auto(v1); // 显式复制,v2 是 std::vector<int>
-
-
多维
operator[]
(mdspan
支持)-
允许自定义多维下标运算符:
struct Matrix {int data[3][3];int* operator[](size_t i) { return data[i]; }int operator[](size_t i, size_t j) const { return data[i][j]; } // C++23 }; Matrix m; m[1, 2] = 42; // 多维访问
-
-
constexpr
扩展-
支持
constexpr
函数中的std::unique_ptr
和std::shared_ptr
(编译期动态内存管理):constexpr auto create() {auto p = std::make_unique<int>(42);return *p; } static_assert(create() == 42); // 编译期执行
-
-
if consteval
-
检测当前是否在编译期上下文中执行:
constexpr int foo() {if consteval { return 42; } // 编译期分支else { return 0; } }
-
-
[[]]
属性的位置放宽-
允许属性出现在更多位置(如
lambda
捕获列表前):auto func = [][[nodiscard]] () { return 42; };
-
二、标准库增强
-
std::mdspan
(多维视图)-
非拥有的多维数组视图,支持灵活切片和步长:
#include <mdspan> int data[2][3] = {{1, 2, 3}, {4, 5, 6}}; std::mdspan mat(data); std::cout << mat[1, 2]; // 输出 6
-
-
std::print
和std::println
-
简化格式化输出(无需
<format>
显式调用):#include <print> std::println("Hello, {}!", "world"); // 输出: Hello, world!
-
-
std::expected
-
表示可能成功或失败的操作(替代
std::optional
+ 错误码):std::expected<int, std::string> parse_input(std::string_view s) {if (s.empty()) return std::unexpected("Empty input");return 42; } auto result = parse_input("test"); if (result) std::println("{}", *result);
-
-
std::generator
(协程生成器)-
标准库协程生成器(简化
range
实现):#include <generator> std::generator<int> range(int start, int end) {for (int i = start; i < end; ++i) co_yield i; } for (int i : range(1, 5)) std::print("{} ", i); // 输出: 1 2 3 4
-
-
std::flat_map
和std::flat_set
-
基于有序向量的关联容器(性能与内存的折衷):
std::flat_map<int, std::string> fm = {{1, "one"}, {2, "two"}}; fm[3] = "three"; // 自动排序
-
-
`` 改进
-
增强堆栈跟踪功能(调试支持):
#include <stacktrace> void foo() {auto st = std::stacktrace::current();std::println("{}", std::to_string(st)); // 打印调用栈 }
-
-
std::to_underlying
-
转换枚举到其底层类型:
enum class Color : uint8_t { Red = 1, Green }; auto val = std::to_underlying(Color::Green); // uint8_t(2)
-
三、其他实用改进
-
std::byteswap
-
编译期字节交换(用于大小端转换):
constexpr uint32_t x = 0x12345678; constexpr auto y = std::byteswap(x); // 0x78563412
-
-
std::unreachable()
-
标记不可达代码(优化提示):
if (x > 0) do_something(); else std::unreachable(); // 假设 x 永远 > 0
-
-
std::move_only_function
-
仅支持移动的函数包装器(替代
std::function
的部分场景):std::move_only_function<int()> func = [] { return 42; }; auto f2 = std::move(func); // func 变为空
-
-
std::hive
(实验性)-
支持指针稳定的序列容器(类似
std::list
但内存连续):std::hive<int> h = {1, 2, 3}; auto it = h.begin(); ++it; h.erase(it); // 其他迭代器仍有效
-
C++六大默认成员函数
在 C++ 中,如果一个类没有显式定义某些特殊成员函数,编译器会自动生成默认版本。这些默认函数共有 6 个,通常被称为 “六大默认成员函数”(或 “六大特殊成员函数”)。以下是它们的详细说明:
class Example {
public:Example() = default; // 显式要求生成默认构造~Example() = default; // 显式生成默认析构Example(const Example&) = delete; // 禁用拷贝构造Example& operator=(Example&&) = default; // 显式生成移动赋值ClassName& operator=(ClassName&&);
};
1. 默认构造函数 (Default Constructor
)
- 形式:
ClassName()
- 作用: 初始化对象的成员(基本类型不初始化,类类型调用其默认构造)。
- 生成条件: 当类中没有定义任何构造函数时生成。
- 注意: 如果定义了其他构造函数,则不会生成默认构造,需手动添加。
2. 默认析构函数 (Destructor
)
- 形式:
~ClassName()
- 作用: 释放对象资源(成员变量会自动析构)。
- 生成条件: 总是生成,除非显式定义。
- 注意: 若类管理动态资源(如指针),通常需要手动定义析构函数。
3. 默认拷贝构造函数 (Copy Constructor
)
- 形式:
ClassName(const ClassName&)
- 作用: 用同类型的另一个对象初始化新对象(浅拷贝)。
- 生成条件: 当类中未显式定义拷贝构造时生成。
- 注意: 若类包含指针或动态资源,需手动实现深拷贝。
4. 默认拷贝赋值运算符 (Copy Assignment Operator
)
- 形式:
ClassName& operator=(const ClassName&)
- 作用: 将一个对象的值赋给另一个已存在的对象(浅拷贝)。
- 生成条件: 当类中未显式定义拷贝赋值时生成。
- 注意: 类似拷贝构造,需处理深拷贝问题。
5. 默认移动构造函数 (Move Constructor
) (C++11 引入)
- 形式:
ClassName(ClassName&&)
- 作用: 通过“窃取”右值对象的资源来初始化新对象。
- 生成条件: 当类中未显式定义移动构造、拷贝构造、拷贝赋值、析构函数时生成。
- 注意: 适用于优化临时对象的资源转移。
6. 默认移动赋值运算符 (Move Assignment Operator
) (C++11 引入)
- 形式:
ClassName& operator=(ClassName&&)
- 作用: 通过“窃取”右值对象的资源赋值给已存在对象。
- 生成条件: 当类中未显式定义移动赋值、拷贝构造、拷贝赋值、析构函数时生成。
总结表
默认函数 | 形式 | 生成条件(未显式定义时) |
---|---|---|
默认构造函数 | ClassName() | 无任何构造函数 |
析构函数 | ~ClassName() | 总是生成 |
拷贝构造函数 | ClassName(const ClassName&) | 无拷贝构造 |
拷贝赋值运算符 | ClassName& operator=(...) | 无拷贝赋值 |
移动构造函数 (C++11) | ClassName(ClassName&&) | 无拷贝/移动构造、拷贝赋值、析构 |
移动赋值运算符 (C++11) | ClassName& operator=(...) | 无拷贝/移动赋值、拷贝构造、析构 |
关键注意事项
- 浅拷贝问题:默认拷贝构造和拷贝赋值是浅拷贝,可能引发双重释放(需手动实现深拷贝)。
- Rule of Three/Five/Zero:
- 如果定义了拷贝构造、拷贝赋值或析构中的任意一个,通常需要定义全部(C++03)。
- 在 C++11 后,还需考虑移动构造和移动赋值(Rule of Five)。
- 最佳实践是使用
=default
或=delete
明确需求,或遵循 Rule of Zero(依赖智能指针等自动管理资源)。
=default
和=delete
:- 可用
=default
显式要求编译器生成默认实现。 - 用
=delete
禁止特定函数(如禁用拷贝)。
- 可用