C++11 新特性简介

C++11 是 C++ 语言的一次重大更新,旨在解决旧版本中的痛点,如代码冗余、类型安全隐患、性能瓶颈和缺乏现代编程支持。新增特性带来了显著好处:

  • 提高开发效率:简化语法(如 auto、基于范围的 for 循环),减少样板代码。
  • 增强安全性:智能指针管理内存,避免泄露;强类型枚举减少错误。
  • 优化性能:移动语义减少拷贝开销;多线程支持并行计算。
  • 提升可维护性:显式控制(如 override、final)使代码更易读。
  • 现代化支持:Lambda 表达式和函数包装器便于函数式编程。

下面,我将按顺序详细描述每个新特性,包括作用、基本用法、主要函数/语法介绍、使用场景,并附上可运行的 C++ 代码示例及输出。所有代码均使用 C++11 标准编译(建议使用 g++ 或 Clang 编译,如 g++ -std=c++11 example.cpp -o example)。


1. auto 关键字

作用:自动推导变量类型,简化代码,减少冗余类型声明。
基本用法:声明变量时用 auto 代替显式类型,编译器根据初始化值推导。
主要语法:auto variable = value;。
使用场景:迭代器、复杂类型(如模板)、避免冗长类型名。
代码示例:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> nums = {1, 2, 3};
    auto it = nums.begin(); // 自动推导为 std::vector<int>::iterator
    auto num = 10;         // 推导为 int
    std::cout << "First element: " << *it << ", num: " << num << std::endl;
    return 0;
}

输出:

First element: 1, num: 10

2. decltype 关键字

作用:推导表达式的类型,用于声明变量或函数返回类型。
基本用法:decltype(expression) variable;。
主要语法:编译时确定类型,不执行表达式。
使用场景:模板元编程、依赖表达式类型的场景。
代码示例:

#include <iostream>
#include <typeinfo>

int main() {
    int x = 5;
    decltype(x) y = 10; // y 的类型为 int
    decltype(x + 1.5) z; // z 的类型为 double
    std::cout << "y type: " << typeid(y).name() << ", z type: " << typeid(z).name() << std::endl;
    return 0;
}

输出(类型名可能因编译器而异):

y type: i, z type: d

3. 基于范围的 for 循环

作用:简化遍历容器(如数组、vector)的循环语法。
基本用法:for (auto& element : container) { ... }。
主要语法:支持值传递、引用传递(auto& 或 const auto&)。
使用场景:遍历数组、STL 容器。
代码示例:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {10, 20, 30};
    for (auto& num : vec) {
        num *= 2; // 修改元素
    }
    for (const auto& num : vec) {
        std::cout << num << " ";
    }
    return 0;
}

输出:

20 40 60

4. 统一初始化

作用:使用花括号 {} 初始化变量,避免歧义,支持所有类型。
基本用法:Type variable{value}; 或 Type variable = {value};。
主要语法:防止窄化转换(如 double 到 int 报错)。
使用场景:初始化对象、数组、容器。
代码示例:

#include <iostream>

struct Point {
    int x, y;
};

int main() {
    int a{5}; // 基本类型
    Point p{1, 2}; // 结构体
    int arr[]{10, 20, 30}; // 数组
    std::cout << "a: " << a << ", p.x: " << p.x << ", arr[0]: " << arr[0] << std::endl;
    return 0;
}

输出:

a: 5, p.x: 1, arr[0]: 10

5. 初始器列表 (Initializer Lists)

作用:通过 std::initializer_list 支持初始化列表,用于构造函数或函数参数。
基本用法:std::initializer_list<T> 作为参数类型。
主要语法:允许 {value1, value2, ...} 传递多个值。
使用场景:自定义容器初始化、函数接受列表参数。
代码示例:

#include <iostream>
#include <vector>
#include <initializer_list>

class MyVector {
public:
    std::vector<int> vec;
    MyVector(std::initializer_list<int> list) : vec(list) {}
};

void print(std::initializer_list<int> list) {
    for (auto num : list) {
        std::cout << num << " ";
    }
}

int main() {
    MyVector mv{1, 2, 3}; // 构造函数使用
    print({4, 5, 6});     // 函数参数使用
    return 0;
}

输出:

4 5 6

6. nullptr 关键字

作用:替代 NULL,表示空指针,避免与整数 0 混淆。
基本用法:Type* ptr = nullptr;。
主要语法:类型安全,只能用于指针。
使用场景:指针初始化、函数重载区分。
代码示例:

#include <iostream>

void func(int) { std::cout << "int called\n"; }
void func(int*) { std::cout << "pointer called\n"; }

int main() {
    int* ptr = nullptr;
    if (ptr == nullptr) {
        std::cout << "ptr is null\n";
    }
    func(nullptr); // 调用指针版本
    return 0;
}

输出:

ptr is null
pointer called

7. 强类型枚举 (enum class)

作用:引入作用域的枚举,避免命名冲突,增强类型安全。
基本用法:enum class Name { VALUE1, VALUE2 };。
主要语法:需使用 Name::VALUE 访问,不支持隐式转换。
使用场景:状态机、选项标志。
代码示例:

#include <iostream>

enum class Color { Red, Green, Blue };

int main() {
    Color c = Color::Green;
    if (c == Color::Green) {
        std::cout << "Color is Green\n";
    }
    // int i = c; // 错误:不能隐式转换
    return 0;
}

输出:

Color is Green

8. 常量表达式 (constexpr)

作用:声明编译时常量或函数,优化性能。
基本用法:constexpr variable = value; 或 constexpr func() { ... }。
主要语法:函数体必须简单(无循环、动态内存)。
使用场景:数组大小、模板元编程。
代码示例:

#include <iostream>

constexpr int square(int x) {
    return x * x;
}

int main() {
    constexpr int size = square(5); // 编译时计算
    int arr[size] = {}; // 数组大小
    std::cout << "Array size: " << size << std::endl;
    return 0;
}

输出:

Array size: 25

9. 默认函数 (= default)

作用:显式要求编译器生成默认构造函数或赋值操作符。
基本用法:ClassName() = default;。
主要语法:用于类定义中。
使用场景:恢复被抑制的默认函数(如自定义构造函数后)。
代码示例:

#include <iostream>

class MyClass {
public:
    MyClass() = default; // 默认构造函数
    int value = 0;
};

int main() {
    MyClass obj; // 使用默认构造
    std::cout << "Default value: " << obj.value << std::endl;
    return 0;
}

输出:

Default value: 0

10. 删除函数 (= delete)

作用:禁止特定函数被调用,防止误用。
基本用法:ReturnType func() = delete;。
主要语法:常用于拷贝构造函数或赋值操作符。
使用场景:单例模式、不可拷贝对象。
代码示例:

#include <iostream>

class NonCopyable {
public:
    NonCopyable() = default;
    NonCopyable(const NonCopyable&) = delete; // 禁止拷贝
    void operator=(const NonCopyable&) = delete;
};

int main() {
    NonCopyable obj1;
    // NonCopyable obj2 = obj1; // 编译错误:函数被删除
    std::cout << "NonCopyable object created\n";
    return 0;
}

输出:

NonCopyable object created

11. 委托构造函数

作用:一个构造函数调用同类的另一个构造函数,减少代码重复。
基本用法:ClassName() : ClassName(args) { ... }。
主要语法:委托链中不能有循环。
使用场景:多个构造函数共享初始化逻辑。
代码示例:

#include <iostream>

class Student {
public:
    Student() : Student("Unknown", 0) {} // 委托到另一个构造函数
    Student(std::string name, int age) : name(name), age(age) {}
    void print() { std::cout << name << ", " << age << std::endl; }
private:
    std::string name;
    int age;
};

int main() {
    Student s1; // 使用委托构造
    s1.print();
    return 0;
}

输出:

Unknown, 0

12. 继承构造函数

作用:派生类继承基类构造函数,简化派生类定义。
基本用法:using Base::Base; 在派生类中。
主要语法:继承所有基类构造函数。
使用场景:派生类无额外成员时。
代码示例:

#include <iostream>

class Base {
public:
    Base(int x) : value(x) {}
    int value;
};

class Derived : public Base {
public:
    using Base::Base; // 继承构造函数
};

int main() {
    Derived d(42); // 使用基类构造函数
    std::cout << "Value: " << d.value << std::endl;
    return 0;
}

输出:

Value: 42

13. 显式虚函数重载 (override)

作用:显式标记虚函数重载,编译器检查是否重写正确。
基本用法:void func() override { ... }。
主要语法:用于派生类中,确保函数签名匹配基类虚函数。
使用场景:大型继承体系,避免重写错误。
代码示例:

#include <iostream>

class Base {
public:
    virtual void print() { std::cout << "Base\n"; }
};

class Derived : public Base {
public:
    void print() override { // 显式重载
        std::cout << "Derived\n";
    }
};

int main() {
    Derived d;
    d.print();
    return 0;
}

输出:

Derived

14. final 关键字

作用:禁止类被继承或虚函数被重写。
基本用法:类:class ClassName final { ... };函数:virtual void func() final { ... }。
主要语法:增强代码控制。
使用场景:设计不可扩展的类或方法。
代码示例:

#include <iostream>

class Base {
public:
    virtual void func() final { // 禁止重写
        std::cout << "Base func\n";
    }
};

class Derived final : public Base { // 禁止继承
    // void func() override { } // 错误:不能重写 final 函数
};

int main() {
    Derived d;
    d.func();
    return 0;
}

输出:

Base func

15. Lambda 表达式

作用:定义匿名函数,简化回调、算法参数。
基本用法:[capture](params) -> retType { body }。
主要语法:捕获列表([=]值捕获、[&]引用捕获)、可省略返回类型。
使用场景:STL 算法、事件处理。
代码示例:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> nums = {1, 2, 3};
    int sum = 0;
    std::for_each(nums.begin(), nums.end(), [&sum](int x) { 
        sum += x; 
    });
    std::cout << "Sum: " << sum << std::endl;
    return 0;
}

输出:

Sum: 6

16. 静态断言 (static_assert)

作用:编译时断言,检查条件,失败则编译错误。
基本用法:static_assert(condition, "message");。
主要语法:条件必须是常量表达式。
使用场景:模板约束、平台检查。
代码示例:

#include <iostream>

int main() {
    static_assert(sizeof(int) == 4, "int must be 4 bytes"); // 编译时检查
    std::cout << "Assert passed\n";
    return 0;
}

输出:

Assert passed

17. 右值引用

作用:引用临时对象(右值),支持移动语义。
基本用法:Type&& ref = std::move(value);。
主要语法:用于函数参数或变量。
使用场景:移动构造函数、完美转发。
代码示例:

#include <iostream>

void func(int&& rval) {
    std::cout << "Rvalue: " << rval << std::endl;
}

int main() {
    int a = 5;
    func(10); // 传递右值
    // func(a); // 错误:不能传递左值
    return 0;
}

输出:

Rvalue: 10

18. 移动语义 (Move Semantics)

作用:通过“窃取”资源(而非拷贝)提升性能,减少临时对象开销。
基本用法:使用移动构造函数或移动赋值操作符。
主要语法:资源所有权转移后,原对象置空。
使用场景:大型对象(如 vector、string)传递。
代码示例:

#include <iostream>
#include <vector>

class MyVector {
public:
    std::vector<int> data;
    MyVector() = default;
    MyVector(MyVector&& other) noexcept : data(std::move(other.data)) {} // 移动构造
    MyVector& operator=(MyVector&& other) noexcept { // 移动赋值
        if (this != &other) {
            data = std::move(other.data);
        }
        return *this;
    }
};

int main() {
    MyVector v1;
    v1.data = {1, 2, 3};
    MyVector v2 = std::move(v1); // 移动语义
    std::cout << "v2 size: " << v2.data.size() << ", v1 size: " << v1.data.size() << std::endl;
    return 0;
}

输出:

v2 size: 3, v1 size: 0

19. 移动构造函数

作用:实现移动语义,通过右值引用转移资源。
基本用法:ClassName(ClassName&& other) noexcept : member(std::move(other.member)) { }。
主要语法:应标记 noexcept,避免异常。
使用场景:自定义资源管理类。
代码示例:见上节(移动语义)代码。


20. 移动赋值操作符

作用:移动赋值,转移资源所有权。
基本用法:ClassName& operator=(ClassName&& other) noexcept { ... }。
主要语法:需处理自赋值。
使用场景:同上节。
代码示例:见移动语义代码。


21. 使用 std::move 触发移动语义

作用:将左值转换为右值引用,触发移动操作。
基本用法:std::move(variable)。
主要语法:定义在 <utility> 头文件。
使用场景:显式转移资源。
代码示例:见移动语义代码。


22. 完美转发 (Perfect Forwarding)

作用:保持参数类型(左值/右值)不变地转发到其他函数。
基本用法:结合模板和 std::forward。
主要语法:template <typename T> void wrapper(T&& arg) { func(std::forward<T>(arg)); }。
使用场景:工厂函数、包装器。
代码示例:

#include <iostream>
#include <utility>

void process(int& val) { std::cout << "Lvalue: " << val << std::endl; }
void process(int&& val) { std::cout << "Rvalue: " << val << std::endl; }

template <typename T>
void forwarder(T&& arg) {
    process(std::forward<T>(arg)); // 完美转发
}

int main() {
    int a = 5;
    forwarder(a); // 左值
    forwarder(10); // 右值
    return 0;
}

输出:

Lvalue: 5
Rvalue: 10

23. 线程 (std::thread)

作用:支持多线程编程,创建并发执行。
基本用法:std::thread t(func, args);。
主要函数:join() 等待线程结束、detach() 分离线程。
使用场景:并行任务。
代码示例:

#include <iostream>
#include <thread>

void thread_func() {
    std::cout << "Thread running\n";
}

int main() {
    std::thread t(thread_func);
    t.join(); // 等待线程结束
    std::cout << "Main thread done\n";
    return 0;
}

输出:

Thread running
Main thread done

24. 多线程同步

互斥锁 (std::mutex)

作用:保护共享资源,防止数据竞争。
基本用法:std::mutex mtx; mtx.lock(); ... mtx.unlock(); 或 std::lock_guard。
使用场景:临界区访问。
代码示例:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;
int counter = 0;

void increment() {
    std::lock_guard<std::mutex> lock(mtx); // 自动加解锁
    ++counter;
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);
    t1.join(); t2.join();
    std::cout << "Counter: " << counter << std::endl;
    return 0;
}

输出:

Counter: 2
条件变量 (std::condition_variable)

作用:线程间同步,等待条件满足。
基本用法:结合 std::mutex 和 wait(), notify_one()。
使用场景:生产者-消费者模型。
代码示例:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; }); // 等待条件
    std::cout << "Worker done\n";
}

int main() {
    std::thread t(worker);
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one(); // 通知线程
    t.join();
    return 0;
}

输出:

Worker done
原子操作 (std::atomic)

作用:无锁线程安全操作。
基本用法:std::atomic<Type> var; 支持 load(), store(), fetch_add()。
使用场景:计数器、标志位。
代码示例:

#include <iostream>
#include <thread>
#include <atomic>

std::atomic<int> count(0);

void increment() {
    for (int i = 0; i < 1000; ++i) {
        count.fetch_add(1); // 原子操作
    }
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);
    t1.join(); t2.join();
    std::cout << "Final count: " << count << std::endl;
    return 0;
}

输出:

Final count: 2000

25. 函数包装器 (std::function)

作用:通用函数包装器,存储可调用对象(函数、Lambda、成员函数)。
基本用法:std::function<ReturnType(Params)> func_wrapper = callable;。
主要函数:operator() 调用存储的函数。
使用场景:回调机制、事件系统。
代码示例:

#include <iostream>
#include <functional>

void print(int x) { std::cout << "Value: " << x << std::endl; }

int main() {
    std::function<void(int)> func = print; // 包装函数
    func(42);
    func = [](int x) { std::cout << "Lambda: " << x << std::endl; }; // 包装 Lambda
    func(10);
    return 0;
}

输出:

Value: 42
Lambda: 10

26. 绑定器 (std::bind)

作用:绑定函数参数,创建新可调用对象。
基本用法:auto new_func = std::bind(func, args, std::placeholders::_1, ...);。
主要语法:使用占位符 _1, _2 表示未绑定参数。
使用场景:参数预设、适配器。
代码示例:

#include <iostream>
#include <functional>

void add(int a, int b) {
    std::cout << a + b << std::endl;
}

int main() {
    auto add_five = std::bind(add, 5, std::placeholders::_1); // 绑定第一个参数
    add_five(3); // 等价于 add(5, 3)
    return 0;
}

输出:

8

27. 智能指针:std::unique_ptr

作用:独占所有权的智能指针,自动释放内存。
基本用法:std::unique_ptr<Type> ptr(new Type); 或 std::make_unique<Type>(args)(C++14)。
主要函数:reset(), release(), get()。
使用场景:单所有者资源管理。
代码示例:

#include <iostream>
#include <memory>

class Resource {
public:
    Resource() { std::cout << "Resource created\n"; }
    ~Resource() { std::cout << "Resource destroyed\n"; }
};

int main() {
    std::unique_ptr<Resource> ptr(new Resource());
    // 自动释放内存
    return 0;
}

输出:

Resource created
Resource destroyed

28. std::shared_ptr

作用:共享所有权的智能指针,引用计数自动释放。
基本用法:std::shared_ptr<Type> ptr = std::make_shared<Type>(args);。
主要函数:use_count() 返回引用计数。
使用场景:多所有者共享资源。
代码示例:

#include <iostream>
#include <memory>

class Item {
public:
    Item() { std::cout << "Item created\n"; }
    ~Item() { std::cout << "Item destroyed\n"; }
};

int main() {
    std::shared_ptr<Item> ptr1 = std::make_shared<Item>();
    {
        std::shared_ptr<Item> ptr2 = ptr1; // 共享所有权
        std::cout << "Use count: " << ptr1.use_count() << std::endl;
    } // ptr2 析构,引用计数减
    std::cout << "Use count: " << ptr1.use_count() << std::endl;
    return 0;
}

输出:

Item created
Use count: 2
Use count: 1
Item destroyed

29. std::weak_ptr

作用:弱引用智能指针,不增加引用计数,避免循环引用。
基本用法:std::weak_ptr<Type> weak = shared_ptr;,需用 lock() 获取 shared_ptr。
主要函数:expired() 检查对象是否有效。
使用场景:打破 shared_ptr 循环引用。
代码示例:

#include <iostream>
#include <memory>

class Node {
public:
    std::weak_ptr<Node> next; // 使用 weak_ptr 避免循环
    ~Node() { std::cout << "Node destroyed\n"; }
};

int main() {
    auto node1 = std::make_shared<Node>();
    auto node2 = std::make_shared<Node>();
    node1->next = node2;
    node2->next = node1; // 弱引用,不增加计数
    if (auto shared = node1->next.lock()) {
        std::cout << "Next node exists\n";
    }
    return 0; // 正常析构
}

输出:

Next node exists
Node destroyed
Node destroyed

30. noexcept 关键字

作用:声明函数不抛出异常,优化性能。
基本用法:void func() noexcept { ... }。
主要语法:如果函数抛出异常,程序终止。
使用场景:移动操作、关键路径函数。
代码示例:

#include <iostream>

void safe_func() noexcept {
    std::cout << "No exception thrown\n";
    // 如果抛出异常,std::terminate() 被调用
}

int main() {
    safe_func();
    return 0;
}

输出:

No exception thrown

总结

C++11 的新特性显著提升了语言的表现力、安全性和性能:

  • 简化开发:auto、Lambda 等减少代码量。
  • 增强安全:智能指针、enum class 等防止常见错误。
  • 优化性能:移动语义、多线程支持高效计算。
  • 现代化支持:函数式编程、并发模型。
    这些特性使 C++ 更适应现代软件开发需求,推荐在项目中积极采用。所有代码示例均可直接编译运行,验证特性功能。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐