【GiraKoo】C++11的新特性

C++11 新特性

核心语言特性

1. 自动类型推导 (auto)

  • 当我们写错了一个变量的类型,例如:int a = "abc";。编译器可以在编译期间,就明确当前代码有误。
  • 既然编译器明确的知道,等号右边的类型是什么,那么就不要劳烦开发者自己操心应该用什么类型了。
cpp 复制代码
auto i = 5;          // int
auto str = "hello";  // const char*

2. 基于范围的 for 循环

  • 简化容器遍历,代码更简洁易读。
cpp 复制代码
std::vector<int> vec{1,2,3};
for (auto& num : vec) { /* 操作每个元素 */ }

3. Lambda 表达式

  • 开发者经常为编写一个合适的函数名,感到头疼。很多函数只使用一次,一个漂亮又贴切的命名,其实并没有那么重要。
  • 那么就不要再劳心劳力的为这种一次性函数起名字了。
cpp 复制代码
auto sum = [](int a, int b) { return a + b; };

std::vector<int> vec{3, 1, 4, 1, 5};
std::sort(vec.begin(), vec.end(), [](int a, int b){ return a > b; });

4. 右值引用,移动语义,完美转发 (&&, std::move, std::forward)

  • 非常重要,可以显著提高代码在对象拷贝时的性能。
  • 但是语法比较违反直觉,必须跳出常规编程的一些思维模式。
  • 在函数参数和返回值中,移动语义会真正体现出优势。
cpp 复制代码
std::string s1 = "Hello";
std::string s2 = std::move(s1);  // s1 资源转移给 s2
std::cout << s2 << std::endl;  // 输出 "Hello"
std::cout << s1 << std::endl;  // 输出空字符串,s1 已失效

5. nullptr 关键字

  • NULL是通过宏定义实现的0,存在类型安全问题
  • nullptr 是类型安全的空指针替代 NULL
nullptr 相比 NULL 的优势:
5.1 类型安全
cpp 复制代码
void func(int x) { std::cout << "int: " << x << std::endl; }
void func(char* ptr) { std::cout << "char*: " << ptr << std::endl; }

// 使用 NULL 会产生歧义
func(NULL);     // 可能调用 func(int),因为 NULL 是 0
func(nullptr);  // 明确调用 func(char*),类型安全
5.2 模板中的类型推导
cpp 复制代码
template<typename T>
void process(T* ptr) {
    if (ptr != nullptr) {  // 清晰明确
        // 处理指针
    }
}

// NULL 在模板中可能被推导为 int 类型
// nullptr 始终是指针类型
5.3 避免整数与指针混淆
cpp 复制代码
int* ptr1 = NULL;     // NULL 本质是 0
int* ptr2 = nullptr;  // nullptr 是真正的空指针常量

if (ptr1 == 0) { }    // 可以编译,但语义不清
if (ptr2 == nullptr) { } // 语义明确
5.4 更好的代码可读性
cpp 复制代码
int* ptr = nullptr;  // 一眼就知道这是空指针

6. 强类型枚举 (enum class)

  • 避免命名冲突,禁止隐式转换
  • 提供作用域限定,避免全局命名空间污染
cpp 复制代码
enum class Color { Red, Green, Blue };
Color c = Color::Red;
// int x = Color::Red;  // 编译错误,禁止隐式转换

7. 常量表达式 (constexpr)

  • 编译时计算,提升运行时性能
cpp 复制代码
constexpr int square(int x) { return x * x; }
int arr[square(5)];  // 编译时确定数组大小

8. 委托构造函数

  • 构造函数调用同类其他构造函数,避免重复代码
cpp 复制代码
class MyClass {
public:
    MyClass(int a) : x(a) {}
    MyClass() : MyClass(0) {}  // 委托
};

9. overridefinal 关键字

  • 明确虚函数覆盖/禁止覆盖
  • 在代码维护时,可以确保多态能够正常工作。
  • 如果不小心修改了基类或者派生类的签名,编译器可以通过明确的报错,确保不会出现多态变成同名覆盖。
cpp 复制代码
class Base {
    virtual void foo() {}     // 可以被覆盖
    virtual void bar() final; // 禁止派生类覆盖
};
class Derived : public Base {
    void foo() override;  // 显式声明覆盖
    // void bar() override; // 编译错误,final禁止覆盖
};

10. 变长模板 (Variadic Templates)

  • 支持任意数量模板参数
cpp 复制代码
template<typename... Args>
void print(Args... args) { /* 递归展开 */ }

11. 统一初始化语法(大括号初始化)

  • 提供统一的初始化语法,适用于所有类型
  • 防止窄化转换,提高类型安全
cpp 复制代码
int x{5};                    // 基本类型
std::vector<int> v{1, 2, 3}; // 容器
struct Point { int x, y; };
Point p{10, 20};             // 聚合类型

12. decltype 关键字

  • 推导表达式的类型,常用于模板编程
cpp 复制代码
int x = 5;
decltype(x) y = 10;  // y 的类型是 int

template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
    return t + u;
}

13. 默认和删除函数

  • 显式控制编译器生成的特殊成员函数
cpp 复制代码
class MyClass {
public:
    MyClass() = default;              // 使用默认构造函数
    MyClass(const MyClass&) = delete; // 禁止拷贝构造
    MyClass& operator=(const MyClass&) = delete; // 禁止拷贝赋值
};

标准库增强

1. 智能指针

  • 这里涉及到一个RAII的概念,通过避免使用裸指针的方式,实现自动内存管理。

  • std::unique_ptr:独占所有权,禁止拷贝和赋值

  • std::shared_ptr:强引用,共享所有权,通过引用计数的方式,实现内存自动管理(引用计数为0时,释放对象)

  • std::weak_ptr:弱引用,避免循环引用,不会增加引用计数,不能直接访问对象

cpp 复制代码
auto ptr = std::make_unique<int>(10);
auto strong = std::make_shared<int>(10);
auto weak = std::weak_ptr<int>(strong);

2. 容器改进

  • 初始化列表:std::vector<int> v = {1, 2, 3};
  • 新增容器:
    • std::array:固定大小数组
    • std::forward_list:单向链表
    • std::unordered_set/map:哈希容器

3. 正则表达式 (<regex>)

cpp 复制代码
std::regex pattern("\\d+");
bool match = std::regex_search("123abc", pattern);

4. 多线程支持 (<thread>, <mutex>, <future>)

  • future是一个非常重要的关键字,后续会单独进行详细说明
cpp 复制代码
std::thread t([](){ std::cout << "Hello Thread!"; });
t.join();

5. 时间库 (<chrono>)

cpp 复制代码
auto start = std::chrono::steady_clock::now();
// ... 执行代码
auto dur = std::chrono::steady_clock::now() - start;

6. 元组 (std::tuple)

  • 允许将多个对象组合成一个对象,并访问组合对象中的元素
  • 之前可能需要返回一个自定义结构体的情况,现在可以直接使用元组
  • 之前函数返回值只能返回一个值,现在可以通过返回元组,实现返回多个值
cpp 复制代码
std::tuple<int, std::string> tup(1, "text");
auto val = std::get<1>(tup);  // "text"

其他重要特性

1. 类型别名 (using 替代 typedef)

cpp 复制代码
template<typename T>
using Vec = std::vector<T>;  // 模板别名

2. 静态断言 (static_assert)

cpp 复制代码
static_assert(sizeof(int) == 4, "32-bit required");

3. 属性语法 ([[attributes]])

cpp 复制代码
[[deprecated("Use new_func()")]] void old_func();

4. 原始字符串字面量

  • 避免转义字符的复杂性,特别适用于正则表达式和文件路径
cpp 复制代码
std::string path = R"(C:\Users\Name\Documents)";
std::string regex = R"(\d{4}-\d{2}-\d{2})";

5. 线程局部存储 (thread_local)

  • 每个线程都有自己的变量副本
cpp 复制代码
thread_local int counter = 0;  // 每个线程独立的计数器

完整示例(综合使用)

cpp 复制代码
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
#include <thread>
#include <future>

class Calculator {
public:
    Calculator() = default;
    Calculator(const Calculator&) = delete;
    Calculator& operator=(const Calculator&) = delete;
    
    template<typename... Args>
    auto sum(Args... args) -> decltype((args + ...)) {
        return (args + ...);
    }
};

int main() {
    // 统一初始化 + auto
    auto nums = {1, 2, 3, 4, 5};
    
    // 智能指针 + 基于范围的循环
    std::vector<std::unique_ptr<int>> ptrs;
    for (auto&& num : nums) {
        ptrs.emplace_back(std::make_unique<int>(num));
    }
    
    // Lambda 表达式 + 移动语义
    auto print = [vec = std::move(ptrs)]() {
        for (const auto& p : vec) {
            std::cout << *p << " ";
        }
        std::cout << std::endl;
    };
    
    // 异步执行
    auto future = std::async(std::launch::async, print);
    future.wait();
    
    // 强类型枚举
    enum class Status { Ready, Running, Done };
    Status status = Status::Done;
    
    // constexpr 函数
    constexpr auto square = [](int x) constexpr { return x * x; };
    static_assert(square(5) == 25, "Compile-time calculation");
    
    return 0;
}

这些特性显著提升了 C++ 的表达能力、安全性和性能,奠定了现代 C++ 开发的基础。后续标准(C++14/17/20)在此基础上进行了扩展和完善。

相关推荐
paopaokaka_luck23 分钟前
基于SpringBoot+Uniapp的健身饮食小程序(协同过滤算法、地图组件)
前端·javascript·vue.js·spring boot·后端·小程序·uni-app
Villiam_AY27 分钟前
Redis 缓存机制详解:原理、问题与最佳实践
开发语言·redis·后端
朝朝又沐沐3 小时前
算法竞赛阶段二-数据结构(36)数据结构双向链表模拟实现
开发语言·数据结构·c++·算法·链表
魔尔助理顾问4 小时前
系统整理Python的循环语句和常用方法
开发语言·后端·python
程序视点4 小时前
Java BigDecimal详解:小数精确计算、使用方法与常见问题解决方案
java·后端
你的人类朋友4 小时前
❤️‍🔥微服务的拆分策略
后端·微服务·架构
逝雪Yuki4 小时前
Leetcode——287. 寻找重复数
c++·leetcode·二分查找·双指针·环形链表
李永奉5 小时前
C语言-流程控制语句:for循环语句、while和do…while循环语句;
c语言·开发语言·c++·算法
AI小智6 小时前
后端变全栈,终于可以给大家推出我的LangChain学习小站了!
后端
打码农的篮球6 小时前
STL——list
开发语言·c++·list