C++的发展

  • 早期的 C++ 被称为 “C with Classes”,引入了类(Class)概念,以及构造函数、析构函数和基本的面向对象编程支持。
  • 1983 年,“C++” 的名字首次出现,代表着比 C 更进一步,同年,第一个正式的 C++ 编译器 Cfront 诞生,这是基于 C 编译器的一个预处理器。
  • 1998 年,C++98,成为第一个 ISO 标准版本。
  • 2003 年,C++03,是对 C++98 的小幅修订,主要修复了细节问题。
  • 2011 年,C++11,C++的崛起,引入了许多革命性特性。如:auto 关键字、Lambda 表达式等。
  • 2014 年,C++14,小幅改进 C++11,增强了 Lambda 表达式和标准库。
  • 2017 年,C++17,新增特性包括结构化绑定(Structured Bindings)、std::optional 和 文件系统支持。更关注现代开发需求,尤其是代码可读性和性能优化。
  • 2020 年,C++20,大规模升级,包括概念(Concepts)、协程(Coroutines)和模块化(Modules),C++20 被认为是现代 C++ 的一个里程碑。
  • 2023 年,C++23,继续改进协程和标准库。

    C++11 新特性

    auto 关键字

    见文章Lambda表达式

    decltype 关键字

    decltype 可用于获取表达式的类型
    1
    2
    int x = 42;
    decltype(x) y = 10; // y 的类型为 int

    lambda 表达式

    见文章Lambda表达式

右值引用

  • 左值:指可以出现在赋值操作符左边的表达式,表示一个内存位置,可以取地址。
  • 右值:指不能出现在赋值操作符左边的表达式,通常是临时对象或字面值,表示一个值而不是一个内存位置。
  • 左值引用:左值引用是对左值的引用,可以通过 & 符号来定义。左值引用允许我们通过引用来访问和修改对象。
    1
    2
    3
    int a = 10;
    int &ref = a; // ref 是 a 的左值引用
    ref = 20; // 修改 ref 也会修改 a
  • 右值引用:通过 && 符号来定义。右值引用允许我们捕获和修改临时对象,主要用于实现移动语义和完美转发。
    1
    2
    int &&rref = 10; // rref 是一个右值引用,引用了临时右值 10
    rref = 20; // 修改 rref
  • 移动语义:右值引用的核心意义在于引入移动语义,优化对象的拷贝行为。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include <iostream>
    #include <string>

    class MyString {
    std::string data;
    public:
    MyString(const std::string& str) : data(str) {} // 拷贝构造函数
    MyString(std::string&& str) : data(std::move(str)) {} // 移动构造函数
    };

    int main() {
    std::string str = "Hello";
    MyString obj1(str); // 调用拷贝构造函数
    MyString obj2(std::move(str)); // 调用移动构造函数
    return 0;
    }
    • 拷贝构造函数: 会将 str 的内容逐字复制到新的对象中。
    • 移动构造函数: 会“搬走”str 的内容,避免浪费内存和时间

      nullptr

      取代旧的 NULL 指针,避免类型不明确的问题。

      智能指针

      引入了两种常用智能指针,替代传统指针,解决资源管理问题:
  • std::unique_ptr: 独占所有权。
  • std::shared_ptr: 共享所有权。
1
2
3
#include <memory>
auto ptr = std::make_shared<int>(10); // 创建 shared_ptr
std::cout << *ptr << std::endl; // 输出 10

constexpr

用于在编译时计算常量表达式。它可以用于变量、函数和构造函数,以提高程序的性能和安全性。

1
2
constexpr int square(int x) { return x * x; }
constexpr int result = square(5); // result 在编译时计算

范围for循环

用于简化容器和数组的遍历

1
2
3
4
std::vector<int> vec = {1, 2, 3};
for (auto x : vec) {
std::cout << x << " ";
}

默认与删除的函数

显式声明函数为默认或禁止:

1
2
3
4
5
class MyClass {
public:
MyClass() = default; // 使用默认构造函数
MyClass(const MyClass&) = delete; // 禁止拷贝构造函数
};

function模板类

  • 是 C++11 中引入的一个模板类,用来包装任何可调用对象,如普通函数、Lambda 表达式、函数指针、成员函数、仿函数等。它使得函数和函数指针可以像对象一样传递和使用,提供了更大的灵活性。
  • 用法示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <iostream>
    #include <functional>

    void printMessage(const std::string& message) {
    std::cout << message << std::endl;
    }

    int main() {
    std::function<void(const std::string&)> func = printMessage; //定义了一个变量,用来存储输入类型为const std::string&,输出类型为void的函数。并给其赋值,像使用变量一样。
    func("Hello, <functional>!");
    return 0;
    }