C++ Primer 第19章:特殊工具与技术
19.1 控制内存分配
19.1.1 重载 new 和 delete
// overload_new_delete.cpp -- 重载new和delete
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
// ===== 全局 new/delete 重载 =====
// 通常不建议重载全局版本,会影响所有内存分配
// ===== 类级别的 new/delete 重载 =====
class MyClass
{
public:
MyClass(int v = 0) : val_(v)
{
std::cout << "[构造] val=" << val_ << std::endl;
}
~MyClass()
{
std::cout << "[析构] val=" << val_ << std::endl;
}
// 重载 operator new:分配内存
static void* operator new(std::size_t size)
{
std::cout << "[new] 分配 " << size << " 字节" << std::endl;
void* p = std::malloc(size);
if (!p) throw std::bad_alloc();
return p;
}
// 重载 operator delete:释放内存
static void operator delete(void* p, std::size_t size) noexcept
{
std::cout << "[delete] 释放 " << size << " 字节" << std::endl;
std::free(p);
}
// 重载数组版本
static void* operator new[](std::size_t size)
{
std::cout << "[new[]] 分配 " << size << " 字节" << std::endl;
void* p = std::malloc(size);
if (!p) throw std::bad_alloc();
return p;
}
static void operator delete[](void* p, std::size_t size) noexcept
{
std::cout << "[delete[]] 释放 " << size << " 字节" << std::endl;
std::free(p);
}
int val() const { return val_; }
private:
int val_;
};
int main()
{
using namespace std;
cout << "===== 单个对象 =====" << endl;
MyClass* p = new MyClass(42); // 调用 operator new,然后构造函数
cout << "val = " << p->val() << endl;
delete p; // 调用析构函数,然后 operator delete
cout << "\n===== 对象数组 =====" << endl;
MyClass* arr = new MyClass[3]; // 调用 operator new[]
delete[] arr; // 调用 operator delete[]
return 0;
}
19.1.2 定位 new(placement new)
// placement_new.cpp -- 定位new
#include <iostream>
#include <new>
#include <string>
class Widget
{
public:
Widget(const std::string& name) : name_(name)
{
std::cout << "[构造] " << name_ << std::endl;
}
~Widget()
{
std::cout << "[析构] " << name_ << std::endl;
}
void show() const { std::cout << "Widget: " << name_ << std::endl; }
private:
std::string name_;
};
int main()
{
using namespace std;
// ===== 定位new:在指定内存上构造对象 =====
// 语法:new (地址) 类型(参数)
// 在栈上分配内存
alignas(Widget) char buffer[sizeof(Widget)];
// 在 buffer 上构造 Widget(不分配内存)
Widget* p = new (buffer) Widget("栈上的Widget");
p->show();
// 必须手动调用析构函数!(不能用 delete)
p->~Widget();
// ===== 在堆上预分配内存,然后构造 =====
void* raw = ::operator new(sizeof(Widget)); // 只分配内存
Widget* p2 = new (raw) Widget("堆上的Widget");
p2->show();
p2->~Widget(); // 手动析构
::operator delete(raw); // 手动释放内存
// ===== 对象池示例 =====
cout << "\n===== 对象池 =====" << endl;
const int POOL_SIZE = 3;
alignas(Widget) char pool[sizeof(Widget) * POOL_SIZE];
// 在池中构造多个对象
Widget* widgets[POOL_SIZE];
for (int i = 0; i < POOL_SIZE; i++)
{
widgets[i] = new (pool + i * sizeof(Widget))
Widget("池对象" + to_string(i));
}
for (int i = 0; i < POOL_SIZE; i++)
widgets[i]->show();
// 手动析构(逆序)
for (int i = POOL_SIZE - 1; i >= 0; i--)
widgets[i]->~Widget();
return 0;
}
19.2 运行时类型识别(RTTI)
19.2.1 dynamic_cast
// dynamic_cast_demo.cpp -- dynamic_cast详解
#include <iostream>
#include <memory>
#include <string>
class Shape
{
public:
virtual double area() const = 0;
virtual std::string name() const = 0;
virtual ~Shape() {}
};
class Circle : public Shape
{
public:
Circle(double r) : radius_(r) {}
double area() const override { return 3.14159 * radius_ * radius_; }
std::string name() const override { return "Circle"; }
double radius() const { return radius_; }
private:
double radius_;
};
class Rectangle : public Shape
{
public:
Rectangle(double w, double h) : w_(w), h_(h) {}
double area() const override { return w_ * h_; }
std::string name() const override { return "Rectangle"; }
double width() const { return w_; }
double height() const { return h_; }
private:
double w_, h_;
};
int main()
{
using namespace std;
Shape* shapes[] = {
new Circle(5.0),
new Rectangle(4.0, 6.0),
new Circle(3.0)
};
cout << "===== dynamic_cast 指针版本 =====" << endl;
for (auto s : shapes)
{
cout << s->name() << " 面积=" << s->area() << endl;
// 向下转型:成功返回有效指针,失败返回 nullptr
if (Circle* c = dynamic_cast<Circle*>(s))
{
cout << " 半径=" << c->radius() << endl;
}
else if (Rectangle* r = dynamic_cast<Rectangle*>(s))
{
cout << " 宽=" << r->width() << " 高=" << r->height() << endl;
}
}
cout << "\n===== dynamic_cast 引用版本 =====" << endl;
// 引用版本:失败时抛出 std::bad_cast
try
{
Shape& s = *shapes[0]; // Circle
Circle& c = dynamic_cast<Circle&>(s); // 成功
cout << "Circle半径:" << c.radius() << endl;
Shape& s2 = *shapes[1]; // Rectangle
Circle& c2 = dynamic_cast<Circle&>(s2); // 失败!抛出 bad_cast
}
catch (const bad_cast& e)
{
cout << "bad_cast:" << e.what() << endl;
}
for (auto s : shapes) delete s;
return 0;
}
19.2.2 typeid 运算符
// typeid_demo.cpp -- typeid运算符
#include <iostream>
#include <typeinfo>
#include <string>
class Base
{
public:
virtual ~Base() {}
virtual std::string type() const { return "Base"; }
};
class Derived : public Base
{
public:
std::string type() const override { return "Derived"; }
};
int main()
{
using namespace std;
// ===== typeid 基本用法 =====
int i = 42;
double d = 3.14;
string s = "Hello";
// typeid 返回 type_info 对象的引用
cout << "int: " << typeid(i).name() << endl;
cout << "double: " << typeid(d).name() << endl;
cout << "string: " << typeid(s).name() << endl;
// ===== typeid 与多态 =====
cout << "\n===== 多态类型 =====" << endl;
Base b;
Derived d2;
Base* p1 = &b;
Base* p2 = &d2;
// 对指针使用 typeid:返回指针类型(不是所指对象的类型)
cout << "typeid(p1): " << typeid(p1).name() << endl; // Base*
// 对解引用指针使用 typeid:返回实际对象类型(动态类型)
cout << "typeid(*p1): " << typeid(*p1).name() << endl; // Base
cout << "typeid(*p2): " << typeid(*p2).name() << endl; // Derived
// ===== 类型比较 =====
cout << "\n===== 类型比较 =====" << endl;
cout << boolalpha;
cout << "p1指向Base:" << (typeid(*p1) == typeid(Base)) << endl;
cout << "p2指向Derived:" << (typeid(*p2) == typeid(Derived)) << endl;
cout << "p1和p2类型相同:" << (typeid(*p1) == typeid(*p2)) << endl;
// ===== 实际应用:类型安全的操作 =====
cout << "\n===== 类型安全操作 =====" << endl;
Base* shapes[] = {new Base(), new Derived(), new Base()};
for (auto s : shapes)
{
if (typeid(*s) == typeid(Derived))
cout << "这是Derived对象" << endl;
else
cout << "这是Base对象" << endl;
delete s;
}
return 0;
}
19.3 枚举类型
// enum_types.cpp -- 枚举类型
#include <iostream>
#include <string>
// ===== 传统枚举(不限定作用域)=====
enum Color { RED, GREEN, BLUE }; // RED=0, GREEN=1, BLUE=2
enum Status { ACTIVE, INACTIVE };
// ⚠️ 传统枚举的问题:
// 1. 枚举值泄漏到外层作用域
// 2. 不同枚举类型可以比较(隐式转换为int)
// 3. 不能指定底层类型(默认int)
// ===== 限定作用域的枚举(C++11)=====
enum class Direction { NORTH, SOUTH, EAST, WEST };
enum class Permission : uint8_t // 指定底层类型
{
NONE = 0,
READ = 1,
WRITE = 2,
EXECUTE = 4,
ALL = READ | WRITE | EXECUTE
};
// ===== 枚举的前置声明(C++11)=====
enum class Season : int; // 前置声明
void printSeason(Season s);
enum class Season : int { SPRING, SUMMER, AUTUMN, WINTER };
void printSeason(Season s)
{
switch (s)
{
case Season::SPRING: std::cout << "春天" << std::endl; break;
case Season::SUMMER: std::cout << "夏天" << std::endl; break;
case Season::AUTUMN: std::cout << "秋天" << std::endl; break;
case Season::WINTER: std::cout << "冬天" << std::endl; break;
}
}
int main()
{
using namespace std;
// 传统枚举
Color c = RED;
int n = c; // ✅ 隐式转换为int
// Color c2 = 0; // ❌ 不能从int转换
// 不同枚举类型可以比较(危险!)
// if (RED == ACTIVE) {} // 编译通过,但语义错误
// 限定作用域枚举
Direction d = Direction::NORTH;
// int m = d; // ❌ 不能隐式转换
int m = static_cast<int>(d); // ✅ 必须显式转换
// 不同枚举类型不能比较
// if (Direction::NORTH == Season::SPRING) {} // ❌ 编译错误
// 权限枚举
Permission perm = Permission::READ;
cout << "READ = " << static_cast<int>(perm) << endl;
// 使用位运算(需要显式转换)
auto combined = static_cast<Permission>(
static_cast<uint8_t>(Permission::READ) |
static_cast<uint8_t>(Permission::WRITE));
cout << "READ|WRITE = " << static_cast<int>(combined) << endl;
// 季节枚举
printSeason(Season::AUTUMN);
// 枚举的大小
cout << "\n枚举大小:" << endl;
cout << "Color: " << sizeof(Color) << " 字节" << endl;
cout << "Permission: " << sizeof(Permission) << " 字节" << endl;
return 0;
}
19.4 类成员指针
// member_pointer.cpp -- 类成员指针
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
class Screen
{
public:
using Action = Screen& (Screen::*)(); // 成员函数指针类型别名
Screen(int h, int w, char c)
: height_(h), width_(w), contents_(h * w, c), cursor_(0) {}
// 成员函数
Screen& home() { cursor_ = 0; return *this; }
Screen& end() { cursor_ = contents_.size() - 1; return *this; }
Screen& forward()
{
if (cursor_ < contents_.size() - 1) ++cursor_;
return *this;
}
Screen& back()
{
if (cursor_ > 0) --cursor_;
return *this;
}
char get() const { return contents_[cursor_]; }
int pos() const { return cursor_; }
// 数据成员
int height_, width_;
std::string contents_;
int cursor_;
};
int main()
{
using namespace std;
Screen s(3, 5, 'X');
// ===== 数据成员指针 =====
// 声明:类型 类名::*指针名
int Screen::*pHeight = &Screen::height_;
int Screen::*pWidth = &Screen::width_;
// 通过对象使用成员指针
cout << "height = " << s.*pHeight << endl; // 3
cout << "width = " << s.*pWidth << endl; // 5
// 通过指针使用成员指针
Screen* ps = &s;
cout << "height = " << ps->*pHeight << endl;
// ===== 成员函数指针 =====
// 声明:返回类型 (类名::*指针名)(参数类型)
Screen& (Screen::*pForward)() = &Screen::forward;
Screen& (Screen::*pBack)() = &Screen::back;
// 通过对象调用
(s.*pForward)();
cout << "前进后位置:" << s.pos() << endl;
(s.*pBack)();
cout << "后退后位置:" << s.pos() << endl;
// 通过指针调用
(ps->*pForward)();
cout << "通过指针前进:" << s.pos() << endl;
// ===== 成员函数指针数组 =====
Screen::Action actions[] = {
&Screen::home,
&Screen::forward,
&Screen::end,
&Screen::back
};
// 执行所有动作
for (auto action : actions)
(s.*action)();
// ===== 使用 std::mem_fn 和 std::bind =====
cout << "\n===== mem_fn 和 bind =====" << endl;
// mem_fn:将成员函数包装为可调用对象
auto getPos = mem_fn(&Screen::pos);
cout << "pos = " << getPos(s) << endl;
// bind:绑定成员函数
auto forward = bind(&Screen::forward, &s);
forward();
cout << "bind forward后:" << s.pos() << endl;
return 0;
}
19.5 嵌套类
// nested_class.cpp -- 嵌套类
#include <iostream>
#include <string>
#include <memory>
// 嵌套类:定义在另一个类内部的类
class TextQuery
{
public:
// 嵌套类:QueryResult
class QueryResult
{
friend class TextQuery;
public:
QueryResult(const std::string& word, int count)
: word_(word), count_(count) {}
void print() const
{
std::cout << "\"" << word_ << "\" 出现 "
<< count_ << " 次" << std::endl;
}
int count() const { return count_; }
private:
std::string word_;
int count_;
};
// TextQuery 的成员
void addWord(const std::string& word)
{
wordCount_[word]++;
}
QueryResult query(const std::string& word) const
{
auto it = wordCount_.find(word);
int count = (it != wordCount_.end()) ? it->second : 0;
return QueryResult(word, count);
}
private:
std::map<std::string, int> wordCount_;
};
// 在类外定义嵌套类的成员
// TextQuery::QueryResult::QueryResult(...) { ... }
int main()
{
using namespace std;
TextQuery tq;
string text = "the quick brown fox jumps over the lazy dog the";
// 分词并统计
istringstream iss(text);
string word;
while (iss >> word)
tq.addWord(word);
// 查询
auto result1 = tq.query("the");
auto result2 = tq.query("fox");
auto result3 = tq.query("cat");
result1.print(); // "the" 出现 3 次
result2.print(); // "fox" 出现 1 次
result3.print(); // "cat" 出现 0 次
return 0;
}
19.6 union:一种节省空间的类
// union_demo.cpp -- union
#include <iostream>
#include <string>
#include <new>
// ===== 基本 union =====
union Data
{
int ival;
double dval;
char cval;
}; // 大小等于最大成员的大小
// ===== 匿名 union =====
struct Token
{
enum class TokenKind { INT, DOUBLE, STRING };
TokenKind kind;
union // 匿名union:成员直接在外层作用域可见
{
int ival;
double dval;
// std::string sval; // ⚠️ 含有构造函数的类型需要特殊处理
};
};
// ===== 含有类类型成员的 union =====
class MyUnion
{
public:
enum class Type { INT, STRING, NONE };
MyUnion() : type_(Type::NONE) {}
MyUnion(int v) : type_(Type::INT)
{
new (&ival_) int(v); // 定位new
}
MyUnion(const std::string& s) : type_(Type::STRING)
{
new (&sval_) std::string(s); // 定位new
}
MyUnion(const MyUnion& other) : type_(other.type_)
{
switch (type_)
{
case Type::INT: new (&ival_) int(other.ival_); break;
case Type::STRING: new (&sval_) std::string(other.sval_); break;
default: break;
}
}
~MyUnion()
{
if (type_ == Type::STRING)
sval_.~basic_string<char>(); // 手动析构
}
void show() const
{
switch (type_)
{
case Type::INT: std::cout << "int: " << ival_ << std::endl; break;
case Type::STRING: std::cout << "string: " << sval_ << std::endl; break;
default: std::cout << "none" << std::endl;
}
}
private:
Type type_;
union
{
int ival_;
std::string sval_;
};
};
int main()
{
using namespace std;
// 基本 union
Data d;
d.ival = 42;
cout << "ival = " << d.ival << endl;
d.dval = 3.14; // 覆盖了 ival
cout << "dval = " << d.dval << endl;
// d.ival 现在是未定义的
cout << "union大小:" << sizeof(Data) << " 字节" << endl;
// 含类类型的 union
MyUnion u1(42);
MyUnion u2(string("Hello"));
MyUnion u3;
u1.show();
u2.show();
u3.show();
return 0;
}
19.7 局部类
// local_class.cpp -- 局部类
#include <iostream>
#include <string>
#include <functional>
// 局部类:定义在函数内部的类
std::function<int(int)> makeAdder(int n)
{
// 局部类
class Adder
{
public:
Adder(int n) : n_(n) {}
int operator()(int x) const { return x + n_; }
private:
int n_;
// ⚠️ 局部类的限制:
// 1. 不能定义静态数据成员
// 2. 不能访问外层函数的局部变量(除非是静态的)
// 3. 可以访问外层函数的类型名、静态变量、枚举值
};
return Adder(n);
}
// 局部类在模板中的应用
template <typename T>
std::function<bool(T)> makeGreaterThan(T threshold)
{
class Comparator
{
public:
Comparator(T t) : threshold_(t) {}
bool operator()(T val) const { return val > threshold_; }
private:
T threshold_;
};
return Comparator(threshold);
}
int main()
{
using namespace std;
auto add5 = makeAdder(5);
auto add10 = makeAdder(10);
cout << "add5(3) = " << add5(3) << endl; // 8
cout << "add10(3) = " << add10(3) << endl; // 13
auto gt5 = makeGreaterThan(5);
auto gt10 = makeGreaterThan(10.0);
cout << boolalpha;
cout << "7 > 5: " << gt5(7) << endl; // true
cout << "3 > 5: " << gt5(3) << endl; // false
cout << "15.0 > 10.0: " << gt10(15.0) << endl; // true
return 0;
}
19.8 固有的不可移植的特性
19.8.1 位域
// bit_fields.cpp -- 位域
#include <iostream>
// 位域:允许将多个标志位打包到一个整数中
struct NetworkPacket
{
unsigned int version : 4; // 4位:版本号(0-15)
unsigned int type : 4; // 4位:类型(0-15)
unsigned int flags : 8; // 8位:标志位
unsigned int length : 16; // 16位:长度(0-65535)
// 总共 32 位 = 4 字节
};
struct Permissions
{
unsigned int read : 1; // 1位
unsigned int write : 1; // 1位
unsigned int execute : 1; // 1位
unsigned int : 5; // 5位填充(未命名)
};
int main()
{
using namespace std;
NetworkPacket pkt;
pkt.version = 4;
pkt.type = 2;
pkt.flags = 0b00000001;
pkt.length = 1024;
cout << "版本:" << pkt.version << endl;
cout << "类型:" << pkt.type << endl;
cout << "标志:" << pkt.flags << endl;
cout << "长度:" << pkt.length << endl;
cout << "结构体大小:" << sizeof(NetworkPacket) << " 字节" << endl;
Permissions perm = {1, 1, 0};
cout << "\n读权限:" << perm.read << endl;
cout << "写权限:" << perm.write << endl;
cout << "执行权限:" << perm.execute << endl;
return 0;
}
19.8.2 volatile 限定符
// volatile_demo.cpp -- volatile
#include <iostream>
// volatile:告诉编译器不要优化该变量
// 每次访问都从内存读取,不使用缓存
// 常见用途:
// 1. 硬件寄存器
// 2. 多线程共享变量(但不能替代互斥锁)
// 3. 信号处理程序中的变量
volatile int hardwareReg = 0; // 模拟硬件寄存器
// volatile 与 const 组合
volatile const int readOnlyReg = 0xFF; // 只读硬件寄存器
void readHardware()
{
// 每次都从内存读取,不会被优化为只读一次
for (int i = 0; i < 3; i++)
std::cout << "寄存器值:" << hardwareReg << std::endl;
}
// volatile 成员函数
class HardwareDevice
{
public:
void read() volatile
{
// 可以被 volatile 对象调用
std::cout << "读取设备" << std::endl;
}
void write() volatile
{
std::cout << "写入设备" << std::endl;
}
};
int main()
{
readHardware();
volatile HardwareDevice dev;
dev.read();
dev.write();
return 0;
}
19.8.3 链接指示(extern "C")
// extern_c.cpp -- 链接指示
#include <iostream>
// extern "C":告诉编译器使用C语言的链接规则
// 主要用于与C代码互操作
// 单个函数
extern "C" void c_function(int x)
{
// 使用C链接,函数名不会被C++名字修饰
std::cout << "C函数:" << x << std::endl;
}
// 多个函数
extern "C"
{
void c_func1() { std::cout << "c_func1" << std::endl; }
void c_func2() { std::cout << "c_func2" << std::endl; }
int c_add(int a, int b) { return a + b; }
}
// 包含C头文件
// extern "C"
// {
// #include <stdio.h>
// #include <string.h>
// }
// 在头文件中同时支持C和C++
#ifdef __cplusplus
extern "C" {
#endif
void shared_function(int x)
{
std::cout << "共享函数:" << x << std::endl;
}
#ifdef __cplusplus
}
#endif
int main()
{
c_function(42);
c_func1();
c_func2();
std::cout << "c_add(3,4) = " << c_add(3, 4) << std::endl;
shared_function(100);
return 0;
}
19.9 综合示例:内存池
// memory_pool.cpp -- 综合示例:内存池
#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>
#include <new>
#include <cstring>
// 固定大小的内存池
template <typename T, size_t BlockSize = 64>
class MemoryPool
{
private:
// 内存块
struct Block
{
alignas(T) char data[sizeof(T)];
bool inUse = false;
};
std::vector<Block> pool_;
size_t allocated_ = 0;
public:
MemoryPool() : pool_(BlockSize) {}
// 分配内存
T* allocate()
{
for (auto& block : pool_)
{
if (!block.inUse)
{
block.inUse = true;
++allocated_;
return reinterpret_cast<T*>(block.data);
}
}
throw std::bad_alloc();
}
// 释放内存
void deallocate(T* p) noexcept
{
for (auto& block : pool_)
{
if (reinterpret_cast<T*>(block.data) == p)
{
block.inUse = false;
--allocated_;
return;
}
}
}
// 构造对象
template <typename... Args>
T* construct(Args&&... args)
{
T* p = allocate();
try
{
new (p) T(std::forward<Args>(args)...); // 定位new
}
catch (...)
{
deallocate(p);
throw;
}
return p;
}
// 析构并释放
void destroy(T* p) noexcept
{
p->~T();
deallocate(p);
}
size_t allocated() const { return allocated_; }
size_t capacity() const { return pool_.size(); }
size_t available() const { return capacity() - allocated(); }
};
// 使用内存池的类
class Widget
{
public:
Widget(const std::string& name, int val)
: name_(name), val_(val)
{
std::cout << "[构造] " << name_ << "(" << val_ << ")" << std::endl;
}
~Widget()
{
std::cout << "[析构] " << name_ << std::endl;
}
void show() const
{
std::cout << "Widget: " << name_ << " = " << val_ << std::endl;
}
private:
std::string name_;
int val_;
};
int main()
{
using namespace std;
MemoryPool<Widget, 5> pool;
cout << "===== 内存池状态 =====" << endl;
cout << "容量:" << pool.capacity() << endl;
cout << "可用:" << pool.available() << endl;
cout << "\n===== 分配对象 =====" << endl;
Widget* w1 = pool.construct("Widget1", 100);
Widget* w2 = pool.construct("Widget2", 200);
Widget* w3 = pool.construct("Widget3", 300);
cout << "已分配:" << pool.allocated() << endl;
w1->show();
w2->show();
w3->show();
cout << "\n===== 释放对象 =====" << endl;
pool.destroy(w2);
cout << "释放w2后,已分配:" << pool.allocated() << endl;
cout << "\n===== 复用内存 =====" << endl;
Widget* w4 = pool.construct("Widget4", 400); // 复用w2的内存
w4->show();
cout << "\n===== 清理 =====" << endl;
pool.destroy(w1);
pool.destroy(w3);
pool.destroy(w4);
cout << "最终已分配:" << pool.allocated() << endl;
return 0;
}
📝 第19章知识点总结
| 知识点 |
核心要点 |
| 重载 new/delete |
类级别重载,operator new 分配内存,operator delete 释放 |
| 定位 new |
new (地址) 类型(参数),在指定内存构造,必须手动调用析构函数 |
| dynamic_cast |
安全向下转型,指针版本失败返回nullptr,引用版本失败抛bad_cast |
| typeid |
返回 type_info,对多态类型返回动态类型,对指针返回静态类型 |
| enum class |
限定作用域,不隐式转换为int,可指定底层类型,推荐使用 |
| 数据成员指针 |
类型 类名::*ptr = &类名::成员,通过 .* 或 ->* 使用 |
| 成员函数指针 |
返回类型 (类名::*ptr)(参数),通过 .* 或 ->* 调用 |
| mem_fn |
将成员函数包装为可调用对象 |
| 嵌套类 |
定义在类内部,有自己的作用域,外层类不能直接访问嵌套类的私有成员 |
| union |
所有成员共享内存,大小等于最大成员,含类类型成员需手动管理 |
| 局部类 |
定义在函数内部,不能有静态数据成员,不能访问外层局部变量 |
| 位域 |
指定成员占用的位数,节省内存,常用于硬件协议 |
| volatile |
防止编译器优化,每次从内存读取,用于硬件寄存器和信号处理 |
| extern "C" |
使用C链接规则,用于C/C++互操作,防止名字修饰 |