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
禁止特定函數(如禁用拷貝)。
- 可用