一、概述
C++11(原名 C++0x)是 ISO/IEC 14882:2011 的正式名称,被誉为 C++ 自 C++98 发布以来最重要的一次升级。它将现代语言的高效抽象(自动类型推导、Lambda、右值引用)与底层性能(移动语义、完美转发、内存序)熔于一炉,直接奠定了后续 C++14/17/20 的现代化范式。
目录
- 类型推导:auto、decltype、拖尾返回类型
- 统一初始化与初始化列表
- nullptr 与强类型枚举 enum class
- 右值引用、移动语义与完美转发
- =default / =delete / 继承构造函数
- Lambda 表达式
- 范围 for 循环
- override / final / default virtual
- 模板别名 using、静态断言 static_assert、noexcept
- 智能指针:unique_ptr / shared_ptr / weak_ptr
- 新增容器:array / forward_list / unordered_map
- 并发与多线程:thread / mutex / condition_variable / async
- 原子操作原子内存序 std::atomic
- 时间库 std::chrono 与随机数 random
- tuple、正则 regex、bind / function
二、核心语言层面改进
2.1 auto / decltype / 拖尾返回类型
语言核心auto:编译器根据初始化表达式自动推导变量类型,彻底解放手写冗长迭代器的负担;注意与初始化同效(不会保留引用/const 顶层)。
decltype(expr):获取表达式的"声明类型",保留 const/引用,是模板泛型编程和类型萃取的基石。
拖尾返回类型(Trailing Return Type):配合 auto + decltype 让返回值依赖形参的函数可被书写(C++14 已升级为直接 auto 返回)。
// auto 示例:编译器从初始化自动推导类型
auto i = 42; // → int
auto d = 3.14; // → double
auto s = "hello"; // → const char* (注意不是 std::string)
auto vec = std::vector<int>{1,2,3};
// C++98 年代需要写一整行迭代器,现在只需:
for (auto it = vec.begin(); it != vec.end(); ++it) { /* ... */ }
// auto 不会保留顶层 const/引用,需要显式声明
const int& ref_i = i;
auto a = ref_i; // → int(拷贝,const& 都被丢弃)
auto& b = ref_i; // → const int&
auto&& c = 100; // → int&&(右值引用绑定纯右值)
const auto& d = ref_i; // → const int&
// decltype:推导表达式的"声明类型"(保留 const/引用)
decltype(ref_i) x = i; // → const int&
decltype((i)) y = i; // → int&(注意双括号 → 左值表达式 → 引用)
decltype(1+2) z = 3; // → int(纯右值)
// 拖尾返回类型:返回值类型依赖参数类型
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
// 进阶:decltype(auto) 示例(此为 C++14,此处对比方便理解)
// template<typename T> decltype(auto) foo(T& x) { return ++x; }
2.2 统一初始化与初始化列表 initializer_list
语法改进引入花括号 {}(brace-init)作为唯一通用的初始化语法,统一了 POD、STL 容器、数组、自定义类的书写;同时支持防止"窄化转换"(int→short、double→int 会报错)。
// (1) 基础类型 & POD 结构体:不再区分 = / () / {}
int a{10}; // C++11 统一语法
double d{3.14};
int arr[]{1,2,3,4};
struct Point { int x, y; };
Point p{100, 200}; // POD 聚合初始化
// (2) STL 容器:无需 push_back 多次
std::vector<int> vi{1,2,3,4,5};
std::map<std::string, int> mp = { {"C++", 98}, {"Rust", 2015} };
// (3) 防止窄化转换(编译错误!)
int big = 100000;
// short s{ big }; // ❌ 错误:narrowing conversion
short s = big; // ✅ 但"="静默截断(推荐用花括号!)
// (4) 自定义类支持 initializer_list 构造
class MyBag {
public:
MyBag(std::initializer_list<int> list) {
for (auto v : list) data_.push_back(v);
}
size_t size() const { return data_.size(); }
private:
std::vector<int> data_;
};
MyBag b{ 1,2,3,4,5 }; // 直接用花括号构造自定义容器
2.3 nullptr 与 enum class 强类型枚举
陷阱修复nullptr:替换 C 时代的宏 NULL(实际是整数 0,易产生重载歧义),它是字面量类型 std::nullptr_t 的值,可隐式转换为任意指针类型,但不能转换为 int/bool(保留唯一显式例外)。
enum class:替换旧枚举,不隐式转整数、不污染外层命名空间、允许指定底层类型,是枚举类的现代首选写法。
/* ---------------- nullptr 解决 NULL 的 3 大经典问题 ---------------- */
void f(int); // #1
void f(char*); // #2
f(0); // ✅ 调用 #1,但用户本意可能是空指针
// f(NULL); // ❌ C++03 二义性 / 大部分实现仍会走 #1
f(nullptr); // ✅ 无歧义走 #2
/* ---------------- enum class 强枚举 ---------------- */
// 传统枚举的问题:隐式转 int + 枚举器泄露到外层作用域
enum OldColor { Red, Green, Blue }; // Red/Green/Blue 泄露
enum OldTraffic { Red, Yellow, Green }; // ❌ 重定义报错!
// C++11 强类型枚举:作用域内、不隐式转整型、可指定底层类型
enum class Color : uint8_t { Red = 1, Green = 2, Blue = 4 };
enum class Traffic : uint8_t { Red, Yellow, Green };
Color c = Color::Green;
int i = static_cast<int>(c); // ✅ 必须显式转整数(= 2)
Traffic t = Traffic::Red; // ✅ 命名空间隔离,不再和 Color::Red 冲突
// 还能前置声明(底层类型必须一致)
enum class Status : int; // 前置声明
Status get(); // 放到头文件里做接口
2.4 右值引用 &&、移动语义、完美转发 std::forward
性能飞跃这是 C++11 对性能影响最大的特性。左值可寻址/有名字;右值不可寻址/临时对象(&& 绑定它)。移动语义避免大对象在函数传参/返回/STL扩容时发生的深拷贝,代之以"窃取资源"。完美转发让模板函数把左/右值属性原样转发给实参,避免多余拷贝,是 emplace_back()、工厂函数的底层实现基础。
class BigBuffer {
public:
explicit BigBuffer(size_t n) : size_(n), data_(new char[n]) {
std::cout << "ctor(size_t)\n";
}
// 深拷贝构造:必须复制堆上的整块内存(昂贵)
BigBuffer(const BigBuffer& o) : size_(o.size_), data_(new char[o.size_]) {
std::memcpy(data_, o.data_, o.size_);
std::cout << "copy ctor (deep copy)\n";
}
// 移动构造:O(1) 偷取对方的指针,避免深拷贝
BigBuffer(BigBuffer&& o) noexcept
: size_(o.size_), data_(o.data_) {
o.size_ = 0;
o.data_ = nullptr; // 把源对象置空,避免 double free
std::cout << "move ctor (steal resources)\n";
}
~BigBuffer() { delete[] data_; }
private:
size_t size_;
char* data_;
};
BigBuffer makeBuffer() {
BigBuffer buf(1024 * 1024); // 1MB 缓冲区
return buf; // C++11 下直接移动(RVO 更优)
}
int main() {
BigBuffer a(1024);
BigBuffer b = a; // 调用深拷贝(因为 a 是左值)
BigBuffer c = std::move(a); // ✅ 调用移动构造,a 变为空
BigBuffer d = makeBuffer(); // ✅ RVO + 移动,零深拷贝
/* -------- 完美转发 std::forward<T> --------- */
// make_unique 的最简化实现:保留左/右值属性送入构造函数
template<typename T, typename... Args>
std::unique_ptr<T> my_make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
std::vector<BigBuffer> v;
v.reserve(10);
v.emplace_back(1024); // ✅ 直接原地构造,无拷贝无移动
}
2.5 =default / =delete / 继承构造函数 using
编译器行为控制=default:显式让编译器生成默认特殊成员(ctor/dtor/copy/move),清晰表达"使用编译器默认版本"。
=delete:显式禁用某个函数(拷贝、移动、甚至某些特化重载),比 C++03"声明成 private 不定义"更直观且编译器能给出更好的错误。
using Base::Base:直接把基类构造函数继承过来,避免在派生类中转写一遍相同签名的构造。
/* =default & =delete 示例 */
class NoCopy {
public:
NoCopy() = default; // 保留默认构造
~NoCopy() = default;
NoCopy(const NoCopy&) = delete; // ❌ 禁止拷贝
NoCopy& operator=(const NoCopy&) = delete;
NoCopy(NoCopy&&) = default; // ✅ 允许移动
NoCopy& operator=(NoCopy&&) = default;
// 进阶技巧:=delete 可以用于任意函数,禁止某些重载
void takeDouble(double);
void takeDouble(int) = delete; // 禁止隐式从 int 提升
};
NoCopy a, b;
// NoCopy c = a; // ❌ 编译错误:已删除的函数
NoCopy d = std::move(a); // ✅ OK(移动)
// takeDouble(42); // ❌ 禁止传入整数参数,避免隐式提升
takeDouble(3.14); // ✅ OK(double)
/* 继承构造函数 using Base::Base */
class Base {
public:
Base(int a, const std::string& b) : x_(a), y_(b) {}
protected:
int x_; std::string y_;
};
class Derived : public Base {
public:
using Base::Base; // ✅ 把 Base(int,string) 构造函数直接"借"过来
void extraWork() { x_ *= 2; }
};
Derived d(100, "hello"); // 等价于直接调用 Base 构造,无需再转写
2.6 Lambda 表达式(闭包)
编程范式把匿名函数直接内嵌在算法调用点,是 C++ 函数式编程的起点。[捕获列表](参数列表) mutable noexcept -> 返回类型 { 函数体 }。捕获模式支持:引用 [&]、值 [=]、表达式初始化(C++14 扩展为广义 lambda capture)。
int main() {
// 形式:[capture](params) -> Ret { body }
auto plusOne = [](int x) -> int { return x + 1; };
std::cout << plusOne(5) << "\n"; // 6
// (1) 按值捕获 [=] :拷贝一份外部变量
int factor = 10;
auto mul = [=](int x) { return x * factor; };
std::cout << mul(6) << "\n"; // 60
// (2) 按引用捕获 [&]:直接操作外部变量
int sum = 0;
std::for_each(v.begin(), v.end(),
[&](int x) { sum += x; });
// (3) 混合捕获:某些按引用,某些按值
std::string name = "C++11";
auto greet = [&sum, name]() { return name + ": sum=" + std::to_string(sum); };
// (4) mutable:允许修改"按值捕获"的副本
int cnt = 0;
auto tick = [=]() mutable { return ++cnt; }; // cnt 的副本自增
tick(); tick(); // 外部 cnt 仍 = 0
// (5) 典型实战:用于 STL 算法 & std::function 回调
std::vector<int> arr{3,1,4,1,5,9,2};
int threshold = 3;
auto gt_cnt = std::count_if(arr.begin(), arr.end(),
[=](int x){ return x > threshold; }); // = 4(4,5,9,≥4 均大于 3 共 4 个)
// 自定义排序规则:按绝对值降序
std::sort(arr.begin(), arr.end(), [](int a, int b) {
return std::abs(a) > std::abs(b);
});
}
2.7 范围 for(Range-based for)
语法糖编译器展开成 for (it = begin; it != end; ++it)。天然支持数组、初始化列表、以及任何有 begin()/end() 的类型(可自定义 ADL 版本)。
std::vector<std::string> names = {"Alice","Bob","Carol"};
// 按值:元素被拷贝(适合小对象)
for (auto s : names) std::cout << s << ' ';
// 按引用:直接修改原容器
for (auto& s : names) s += ".com";
// const 引用:只读最高效(推荐)
for (const auto& s : names) std::cout << s << '\n';
// 原生数组也可使用
int arr[] = {1,2,3,4};
int total = 0;
for (auto e : arr) total += e; // total = 10
// 自定义类型:只要提供 begin()/end()(或 ADL 的 free begin/end)
2.8 override / final
防错override:显式声明"我要重写虚函数",签名不匹配时编译器立刻报错,防止 C++03 常见的"以为是 override,实际是隐藏/重载"。
final:修饰类禁止被继承,修饰虚函数禁止被重写(实现 Java 的 sealed / final)。
struct Base {
virtual void foo(int x) const;
virtual void bar(double d);
virtual ~Base() = default;
};
struct Derived : public Base {
// ❌ 无 override 时的经典 bug:const、参数类型任何不一致,编译器默认是"新函数"
// void foo(int x); // 旧写法,静默变成 Derived::foo(int) 非 const 的全新虚函数
// ✅ 加 override:签名不匹配就编译错误(可及时发现)
void foo(int x) const override;
// final:子类不能再重写 bar 了
void bar(double d) final override;
};
struct Derived2 final : Derived { // final 类:不允许被继承
// void bar(double) override; // ❌ 编译错误:bar 已经在 Derived 中被 final
};
// struct Derived3 : Derived2 {}; // ❌ Derived2 被 final 禁止继承
2.9 using 模板别名 / static_assert / noexcept
using 别名模板:比 typedef 更直观、能直接做模板别名。
static_assert(cond, msg):编译期断言,失败直接输出错误信息,彻底替代 C++03 复杂的 BOOST_STATIC_ASSERT。
noexcept:声明函数"不会抛异常",编译器可据此优化(例如 vector 扩容时优先调用 noexcept 的移动构造)。
/* 1) using 别名模板 */
template<typename T>
using VecMap = std::map<std::string, std::vector<T>>; // 一行搞定模板别名
VecMap<int> userScores; // 等价于 map<string, vector<int>>
VecMap<std::string> userTags; // 等价于 map<string, vector<string>>
/* 2) static_assert 编译期断言 + 标准库 type_traits */
#include <type_traits>
template<typename T>
class PodOnlyContainer {
static_assert(std::is_trivial<T>::value, "T 必须是 trivial(POD) 类型");
static_assert(sizeof(T) <= 1024, "T 过大");
};
PodOnlyContainer<int> a; // OK
// PodOnlyContainer<std::string> b; // ❌ 编译报错,并打印中文消息
/* 3) noexcept:不会抛异常的强承诺,影响 STL 容器扩容策略、std::move_if_noexcept 等 */
struct S {
S(S&&) noexcept { /* 不抛异常 */ } // 推荐给移动 ctor/assignment 加 noexcept
void fastPath() noexcept;
void slowPath(); // 未声明 noexcept 等价于 可能抛异常
};
// std::vector<S> 在 rehash/reallocate 时会直接使用移动构造(而非拷贝构造)
三、标准库层面改进
3.1 智能指针家族:unique_ptr / shared_ptr / weak_ptr
资源安全RAII 自动化内存管理,彻底告别 new/delete。unique_ptr 独占所有权,几乎零开销;shared_ptr 引用计数共享;weak_ptr 打破 shared_ptr 循环引用。三者均是异常安全的基石。
#include <memory>
struct Widget {
int id;
Widget(int i) : id(i) { std::cout << "Widget " << id << " 构造\n"; }
~Widget() { std::cout << "Widget " << id << " 析构\n"; }
};
/* 1) unique_ptr:独占所有权,零开销,可移动不可拷贝 */
{
auto pw = std::unique_ptr<Widget>(new Widget(1));
// 推荐 C++14:auto pw = std::make_unique<Widget>(1); // 防异常泄露
// auto pw2 = pw; // ❌ 禁止拷贝
auto pw3 = std::move(pw); // ✅ 所有权转移
} // ← 作用域结束:自动 delete Widget 1
/* 2) shared_ptr:引用计数共享,最后一个持有者销毁时 delete */
{
auto sp1 = std::make_shared<Widget>(10); // ref=1
{
auto sp2 = sp1; // ref=2
std::cout << "内部作用域 ref=" << sp1.use_count() << '\n';
} // 退出内部 ref=1
} // ← ref 归零 → 自动 delete Widget 10
/* 3) weak_ptr:打破循环引用,不增加引用计数 */
struct Node {
std::shared_ptr<Node> next; // 用 shared_ptr 持有后继节点
std::weak_ptr<Node> prev; // ← 前驱用 weak_ptr,避免双向链表循环泄漏
~Node() { std::cout << "Node 释放\n"; }
};
auto a = std::make_shared<Node>();
auto b = std::make_shared<Node>();
a->next = b; b->prev = a; // ✅ 双链表:无循环引用,离开作用域后 2 个 Node 都会正常释放
// weak_ptr 读取前先 lock(),拿得到才是有效对象
if (auto prev = a->prev.lock()) {
std::cout << "prev alive" << "\n";
}
3.2 新增容器:std::array / std::forward_list / 无序容器
容器补齐std::array<T,N>:静态数组,封装 C 数组,保有 STL 接口(begin/end/size),栈上分配零开销。
std::forward_list<T>:单向链表,比 list 更省内存(无前驱指针),支持 O(1) 的 insert_after。
unordered_map / unordered_set:基于哈希表,平均 O(1) 查找/插入,对应旧版的 hash_map/hash_set(已标准化)。
// 1) std::array —— 栈上定长数组 + STL 接口
std::array<int, 5> arr = {1,2,3,4,5};
std::sort(arr.begin(), arr.end()); // 直接算法
for (auto x : arr) /* ... */;
auto* raw = arr.data(); // 仍可取底层 C 指针(和 C 接口互操作)
// 2) forward_list —— 单向链表,省内存
std::forward_list<int> fl = {1,1,2,3,5,8};
fl.insert_after(fl.before_begin(), 0); // O(1) 插入头部,得到 0,1,1,2,3,5,8
fl.unique(); // 去重:0,1,2,3,5,8
// 3) unordered_map —— 哈希表 O(1) 查找
std::unordered_map<std::string, int> ages = {
{"Yang", 30}, {"Li", 25}, {"Wang", 28}
};
ages["Zhang"] = 27;
auto it = ages.find("Li");
if (it != ages.end()) std::cout << it->second << "\n"; // 25
// 自定义类型做键:需提供 Hash 函数 + operator==(简化示例见 CppReference)
四、并发与多线程(语言第一次原生支持)
4.1 std::thread / std::mutex / condition_variable / std::async
语言级并发C++11 首次将并发模型写入标准:std::thread 跨平台线程;mutex + lock_guard/unique_lock RAII 互斥;condition_variable 条件变量做生产者-消费者;std::async / future / promise 做任务级异步与返回值传递。
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <queue>
/* -------- 1) 最基础 thread + mutex 竞争保护 -------- */
int counter = 0;
std::mutex mtx;
void worker(int id) {
for (int i = 0; i < 1000; ++i) {
std::lock_guard<std::mutex> lock(mtx); // 作用域结束自动 unlock(异常安全)
++counter;
}
}
int main() {
std::thread t1(worker, 1), t2(worker, 2);
t1.join(); t2.join();
std::cout << "counter = " << counter << "\n"; // 恒定 = 2000
}
/* -------- 2) 生产者-消费者:condition_variable -------- */
std::queue<int> g_queue;
std::condition_variable g_cv;
void produce() {
for (int i = 1; i <= 10; ++i) {
{
std::lock_guard<std::mutex> lck(mtx);
g_queue.push(i);
} // 先解锁再通知,性能更好
g_cv.notify_one();
}
}
void consume() {
while (true) {
std::unique_lock<std::mutex> lck(mtx);
g_cv.wait(lck, []{ return !g_queue.empty(); }); // wait 自带谓词版本:自动防虚假唤醒
int v = g_queue.front(); g_queue.pop();
lck.unlock(); // 处理前先解锁,减少临界区
// process v ...
if (v == 10) break;
}
}
/* -------- 3) async / future / promise:拿返回值 -------- */
// 写法 A:std::async — 高级任务 API
std::future<long long> f1 = std::async(std::launch::async, [](){
long long s = 0;
for (int i = 0; i <= 1000000; ++i) s += i;
return s;
});
long long sum = f1.get(); // 阻塞,拿到异步返回值 500000500000
// 写法 B:std::promise + std::future — 手动设置结果 / 异常
std::promise<std::string> prom;
auto fut = prom.get_future();
std::thread([&]{ prom.set_value("Done from worker"); }).detach();
std::cout << fut.get() << "\n"; // "Done from worker"
4.2 原子操作 & 内存序 std::atomic / memory_order
并发底层提供无锁变量原子读写(fetch_add / compare_exchange_strong),同时给出6 种内存序让开发者在"跨线程可见性/顺序约束"与"性能"之间精细调控。C++11 之后并发模型正式进入"数据竞争-free = 顺序一致的多线程语义"。
#include <atomic>
// 最常用:计数器、flag、停止令牌
std::atomic<int> atmCount{0};
std::atomic<bool> atmStop{false};
void worker() {
while (!atmStop.load(std::memory_order_acquire)) {
atmCount.fetch_add(1, std::memory_order_relaxed); // 计数无需顺序
}
}
/* 6 种内存序速查(由强到弱):
* seq_cst = 默认值,顺序一致(最强,几乎无风险)
* acquire / release = 配对使用:读端 acquire 与写端 release 形成同步
* consume = 比 acquire 更弱,只保证数据依赖(实际编译器多退化成 acquire)
* relaxed = 最松,只保证原子性,不保证跨线程顺序
*/
// compare_exchange_strong:经典无锁栈 push 片段
struct Node { int val; Node* next; };
std::atomic<Node*> g_head{nullptr};
void push(int v) {
Node* newNode = new Node{v, nullptr};
newNode->next = g_head.load(std::memory_order_relaxed);
// CAS:若 head 仍是预期值,则改为新节点;失败时内部把 newNode->next 刷新
while (!g_head.compare_exchange_weak(
newNode->next, newNode,
std::memory_order_release,
std::memory_order_relaxed)) {
/* 空转重算 */
}
}
4.3 时间库 std::chrono 与 <random>
基础库chrono 强类型时间点/时长(std::chrono::milliseconds / steady_clock),杜绝"sleep 的第二个参数是 us 还是 ms?"的经典问题。random 用 mt19937 + uniform_int_distribution 替换 C 时代 rand()(线性同余质量差 + 全局状态)。
#include <chrono>
#include <random>
#include <thread>
/* chrono:强类型时长/时间点 */
using namespace std::chrono; // 引入 hours/minutes/seconds/milliseconds 字面量前缀
auto t0 = steady_clock::now(); // steady 稳定时钟,适合计时(不受系统时间回拨影响)
std::this_thread::sleep_for(milliseconds(50)); // 明确 ms,不再有歧义
auto dt = duration_cast<microseconds>(steady_clock::now() - t0);
std::cout << "sleep 实际花费 " << dt.count() << " us\n";
// 类型安全:不做隐式精度丢失转换
// seconds s1 = 3.14; // ❌ 错误(非整数秒)
// milliseconds ms1 = 3s; // ✅ OK(提升精度)
/* <random>:mt19937 + 分布类替换 rand() */
std::random_device rd; // 真随机熵池(硬件支持),用于播种
std::mt19937 gen(rd()); // 伪随机引擎:梅森旋转 19937
std::uniform_int_distribution<> dist1(1, 100); // 均匀整数 [1,100]
std::normal_distribution<double> dist2(0.0, 1.0); // 标准正态分布 N(0,1)
int dice = dist1(gen); // 掷骰子
double noise = dist2(gen); // 加高斯噪声
4.4 tuple 元组、正则 regex、function/bind
std::tuple<T...>:可存任意数量异构元素,配合 tie / make_tuple / get<N> 广泛应用于多返回值、结构化绑定雏形。
std::regex:官方正则库,ECMAScript/awk/grep 多种语法。
std::function / std::bind:统一可调用对象包装;bind 可绑定参数生成新可调用(Lambda 出现后使用场景减少)。
/* 1) tuple:多返回值 / tie 结构化解包 */
std::tuple<std::string, int, double> getUser() {
return std::make_tuple("Yang", 30, 178.5);
}
int main() {
// 方式 1:直接 get<N>(C++11 基本做法)
auto user = getUser();
std::cout << std::get<0>(user) // 姓名 "Yang"
<< std::get<1>(user); // 年龄 30
// 方式 2:std::tie 一次解包到多个左值变量(C++11/14 惯用手段)
std::string name; int age; double height;
std::tie(name, age, height) = getUser();
/* 2) std::regex 示例:提取邮箱 */
#include <regex>
std::string text = "联系邮箱:yang@example.com,抄送到 support@site.org";
std::regex emailPat(R"(([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,}))");
auto it = std::sregex_iterator(text.begin(), text.end(), emailPat);
for (auto end = std::sregex_iterator(); it != end; ++it) {
std::cout << "邮箱:" << (*it)[0] // 整体匹配
<< " 域=" << (*it)[2] << '\n'; // 第 2 组(域名)
}
/* 3) function & bind 统一函数对象 */
#include <functional>
void printSum(int a, int b) { std::cout << a + b << '\n'; }
// function:统一装下所有签名一致的可调用物
std::function<void(int,int)> fn1 = printSum;
std::function<void(int,int)> fn2 = [](int a,int b){ std::cout << a*b << '\n'; };
// bind:把参数"预绑定",生成新的可调用物(Lambda 多数情况下更直观)
auto addOne = std::bind(printSum, std::placeholders::_1, 1);
addOne(41); // → 等价于 printSum(41, 1) = 42
}
五、C++11 新特性速查对照表
| 类别 | 特性 | 典型解决痛点 |
|---|---|---|
| 类型 | auto | 长类型名、迭代器手写冗余 |
| decltype / trailing return | 泛型返回值依赖形参 | |
| using 别名模板 | typedef 不能做模板别名 | |
| 安全/语义 | nullptr | NULL 空指针与整数 0 重载歧义 |
| enum class | 旧枚举隐式转 int、命名污染 | |
| static_assert / noexcept | 编译期断言;STL 扩容走移动 | |
| 性能基石 | && / 移动语义 | 大对象 STL 扩容/返回深拷贝 |
| std::forward 完美转发 | 工厂/emplace 多余拷贝 | |
| 范式拓展 | Lambda | 算法需要仿函数/函数指针 |
| range-for | 迭代器遍历啰嗦 | |
| OOP 纠错 | override / final | 虚函数不匹配但不报错 |
| =default / =delete / 继承构造 | 控制编译器默认行为 | |
| 内存安全 | unique_ptr / shared_ptr / weak_ptr | 裸 new/delete 泄漏、循环引用 |
| initializer_list / {} 统一初始化 | 多种初始化语法不统一 | |
| 并发原生 | thread / mutex / cv / async | POSIX / Win32 平台不一致 |
| std::atomic 内存序 | 无锁编程无标准化内存模型 | |
| chrono / <random> | sleep 单位混乱;rand 质量差 | |
| 容器/库 | array / forward_list | C 数组零抽象;单链表缺位 |
| unordered_map / set | 非标准 hash_map 移植 | |
| tuple / regex / function & bind | 多返回值;正则;回调统一 |
总结 & 迁移建议
C++11 不是"加了几个语法糖"的小版本,而是把类型系统(auto/decltype)、所有权模型(移动语义 + 智能指针)、并发模型(thread + memory model) 三件核心基础设施都升了级。建议项目迁移优先级:
- 立即采纳:智能指针替代裸 new/delete;统一初始化;nullptr;enum class;override/final
- 大力推广:range-for + Lambda + STL 算法替代手写循环;chrono/random 替代 C 函数
- 性能关键点:给自定义大对象补 noexcept 移动构造/赋值,STL 性能可获得数量级提升
- 并发重构:用 thread/mutex/atomic 替换平台相关 pthread / _beginthreadex 宏