学懂C++(五十三):全面解析:C++11 标准及其新特性详解

什么是 C++11 标准?

C++11 是 C++ 语言的一个重大更新标准,它于 2011 年发布,因此被命名为 C++11。这个标准为 C++ 语言引入了许多新的语言特性和库改进,使得程序设计更加简洁、高效,并且更易于维护。C++11 的设计目标是改进 C++ 的可用性、性能和多样性,同时确保向后兼容 C++98/03 标准。

C++11 标准中的主要新特性

C++11 标准引入了以下几大类的新特性:

  1. 语言扩展

    • 类型推导 (auto)
    • 匿名函数(Lambda 表达式)
    • 右值引用和移动语义
    • 新的循环语法(基于范围的 for 循环)
    • 列表初始化
    • 强类型枚举 (enum class)
    • 静态断言(static_assert)
    • 委托构造函数
    • 继承构造函数
    • 变长模板参数
  2. 标准库扩展

    • 智能指针(std::unique_ptrstd::shared_ptr
    • 多线程支持 (std::threadstd::mutex)
    • 原始字面量
    • long long 类型
    • 空指针 nullptr
    • constexpr 关键字
    • final 和 override 关键字
    • 模板的优化
    • 自动推导 decltype
    • using 的使用
  3. 编译器功能改进

    • 静态断言 (static_assert)
    • 强制枚举 (enum class)
    • noexcept 规范

接下来将全面深入讲解 C++11 标准中的主要新特性,并通过代码示例来帮助理解。

语言扩展

1. 类型推导 (auto)

概念
auto 关键字允许编译器根据初始化表达式自动推导变量的类型,减少显式类型声明的冗余,提升代码的可读性。

示例

#include <iostream>
#include <vector>

int main() {
    auto x = 42;       // x 被推导为 int 类型
    auto y = 3.14;     // y 被推导为 double 类型

    std::vector<int> vec = {1, 2, 3, 4, 5};
    for (auto num : vec) {
        std::cout << num << " ";  // 输出 1 2 3 4 5
    }

    return 0;
}

说明
auto 减少了冗余的类型声明,编译器根据初始值的类型推导出变量类型。特别适用于复杂的 STL 容器类型。

2. Lambda 表达式

概念
Lambda 表达式是 C++11 引入的一种匿名函数机制,允许在代码中定义简洁的内联函数,常用于回调函数或 STL 算法中。

示例

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

int main() {
    std::vector<int> nums = {1, 2, 3, 4, 5};

    // 使用 Lambda 表达式打印每个元素
    std::for_each(nums.begin(), nums.end(), [](int num) {
        std::cout << num << " ";  // 输出 1 2 3 4 5
    });

    // Lambda 表达式作为比较函数
    auto sum = [](int a, int b) { return a + b; };
    std::cout << "\nSum: " << sum(5, 3) << std::endl;  // 输出 8

    return 0;
}

说明
Lambda 表达式语法:捕获列表 -> 返回类型 { 函数体 }
[] 是捕获列表,可以用来捕获外部变量,[] 表示不捕获任何变量,[&] 表示按引用捕获所有外部变量,[=] 表示按值捕获所有外部变量。Lambda 表达式常用于回调、函数式编程和 STL 算法。

3. 右值引用与移动语义

概念

        在C++11之前,当我们需要传递或返回对象时,通常会进行对象的复制,这对于某些资源密集型对象来说开销很大。C++11引入了右值引用(&&)和移动语义,使得我们可以通过移动资源而不是复制资源来显著提升性能。

  • 右值引用:右值引用是一种引用类型,它可以绑定到临时对象(右值)。右值引用的主要用途是实现移动语义。
  • 移动语义:移动语义允许对象的资源(如内存、文件句柄等)通过"移动"的方式从一个对象转移到另一个对象,而不是通过复制,从而避免不必要的资源分配和释放。

示例

#include <iostream>
#include <vector>

class Resource {
public:
    int* data;

    Resource() {
        data = new int[1000];  // 动态分配资源
        std::cout << "Resource acquired" << std::endl;
    }

    ~Resource() {
        delete[] data;  // 释放资源
        std::cout << "Resource destroyed" << std::endl;
    }

    // 移动构造函数
    Resource(Resource&& other) noexcept : data(other.data) {
        other.data = nullptr;  // 让源对象不再拥有资源
        std::cout << "Resource moved" << std::endl;
    }

    // 禁用复制构造函数
    Resource(const Resource&) = delete;
};

int main() {
    std::vector<Resource> vec;
    vec.push_back(Resource());  // 触发移动构造函数

    return 0;
}

详细解析

  1. 类定义和资源管理

    • Resource 类包含一个指向动态分配内存的指针 data
    • 构造函数 Resource() 在对象创建时分配内存,并打印 "Resource acquired"。
    • 析构函数 ~Resource() 在对象销毁时释放内存,并打印 "Resource destroyed"。
  2. 移动构造函数

    • 移动构造函数 Resource(Resource&& other) noexcept 是用来处理右值的构造函数。
    • 它接受一个右值引用 other 并将 other 的 data 指针赋值给当前对象。
    • 然后,将 other.data 置为 nullptr,表示 other 不再拥有该资源。
    • noexcept 关键字表示该操作不会抛出异常,这有助于优化移动操作。
  3. 禁用复制构造函数

    • Resource(const Resource&) = delete 禁用了复制构造函数,防止对象被复制。
  4. main 函数中使用

    • 创建一个 std::vector<Resource> 容器。
    • 使用 vec.push_back(Resource()) 添加一个临时 Resource 对象到容器中。
    • 由于 Resource() 创建的是一个临时对象(右值),因此会触发移动构造函数。
    • 移动构造函数将临时对象的资源转移到 std::vector 中的对象,而不是进行复制。

为什么移动语义重要?

  • 性能提升:移动语义避免了不必要的资源分配和释放,提高了性能。例如,在上面的例子中,内存仅被分配一次,然后通过指针的移动来转移所有权。
  • 资源管理:通过移动语义,可以实现更好的资源管理,避免了内存泄漏和资源浪费。

总结

        右值引用与移动语义是C++11引入的重要特性,它们允许我们通过移动而不是复制来高效地管理资源。在示例中,Resource 类展示了如何通过移动构造函数来实现资源的高效转移,而不是进行昂贵的复制操作。这样不仅提升了性能,还简化了资源管理。

核心知识解析:

1)移动构造函数

// 移动构造函数
Resource(Resource&& other) noexcept : data(other.data) {
    other.data = nullptr;  // 让源对象不再拥有资源
    std::cout << "Resource moved" << std::endl;
}

解释:

  1. 函数签名:

    • Resource(Resource&& other) noexcept 是一个移动构造函数。
    • Resource&& 表示该函数接受一个右值引用(通常是一个即将被销毁的临时对象)。
    • noexcept 关键字表示这个函数不会抛出异常,这有助于某些标准库容器的优化。
  2. 初始化列表:

    • : data(other.data) 使用初始化列表将 other 对象中的 data 指针转移到当前对象。
    • 这意味着当前对象将继承 other 的资源,而不需要重新分配内存。
  3. 重置源对象:

    • other.data = nullptr; 将源对象的 data 指针设置为 nullptr
    • 这样做是为了确保源对象不再拥有资源,避免在源对象被销毁时意外释放已被转移的资源。
  4. 日志输出:

    • std::cout << "Resource moved" << std::endl; 打印一条消息,用于调试和验证移动操作的发生。

2)禁用复制构造函数

// 禁用复制构造函数
Resource(const Resource&) = delete;

解释:

  1. 函数签名:

    • Resource(const Resource&) = delete; 禁用了复制构造函数。
    • Resource(const Resource&) 是复制构造函数的默认签名,用于创建一个对象的副本。
  2. 删除操作:

    • = delete 语法显式地告诉编译器,我们不允许使用复制构造函数。
    • 这样,如果代码中有任何尝试复制 Resource 对象的操作,编译器将报错。

为什么删除复制构造函数?

  • 避免资源重复释放:

    • 如果允许复制 Resource 对象,那么多个对象将共享同一个 data 指针。
    • 在这些对象被销毁时,将会尝试多次释放同一块内存,导致未定义行为(常常是程序崩溃)。
  • 推动使用移动语义:

    • 禁用复制构造函数强制用户使用移动构造函数,以确保资源的高效管理和转移。
    • 这也是现代 C++ 编程的推荐做法,以提高性能和安全性。

总结

  • 移动构造函数 (Resource(Resource&& other) noexcept):

    • 用于从一个临时对象(右值)中高效地转移资源。
    • 通过将源对象的 data 指针赋值给当前对象,并将源对象的 data 设置为 nullptr,避免了资源的重复释放。
  • 禁用复制构造函数 (Resource(const Resource&) = delete):

    • 防止对象的复制,避免资源管理问题。
    • 强制用户使用移动语义来管理资源,从而提高程序的性能和安全性。

通过这两者的结合,Resource 类能够高效且安全地管理其资源,避免了传统复制方式带来的潜在问题。

4. 基于范围的 for 循环

概念
基于范围的 for 循环使得对容器元素的迭代更加简洁和直观。

示例

#include <iostream>
#include <vector>

int main() {
    std::vector<int> nums = {1, 2, 3, 4, 5};

    // 使用基于范围的 for 循环迭代
    for (int num : nums) {
        std::cout << num << " ";  // 输出 1 2 3 4 5
    }

    return 0;
}

 

说明
基于范围的 for 循环使得迭代容器更加简洁,无需显式使用迭代器。也可以使用 auto 来自动推导元素类型,进一步简化代码。

5. 列表初始化

概念
C++11 引入了统一的列表初始化语法,可以用 {} 进行初始化。这种初始化方式更加简洁、类型安全,适用于普通类型、容器、结构体和类对象的初始化。

示例

#include <iostream>
#include <vector>

struct Point {
    int x, y;
};

int main() {
    // 用列表初始化基本类型
    int arr[3] = {1, 2, 3};

    // 初始化容器
    std::vector<int> vec = {1, 2, 3, 4};

    // 初始化结构体
    Point p = {10, 20};

    // 输出
    std::cout << "Point: (" << p.x << ", " << p.y << ")" << std::endl;

    return 0;
}

 

说明
列表初始化可以防止窄化转换(即防止不安全的类型转换),例如从 double 转换为 int。列表初始化统一了不同类型的初始化方式,使得代码更加整洁。

6. 强类型枚举 (enum class)

概念
C++11 引入了强类型枚举 enum class,与传统枚举相比,它具有更好的类型安全性。传统的 enum 会将枚举常量提升为整数,而 enum class 则不会自动转换为整数,避免了类型不安全的隐患。

示例

#include <iostream>

enum class Color { Red, Green, Blue };
enum class Fruit { Apple, Orange, Banana };

int main() {
    Color color = Color::Red;
    Fruit fruit = Fruit::Apple;

    // 错误:不能隐式转换 enum class 类型
    // int colorValue = color;

    // 正确:显式转换为整数
    int colorValue = static_cast<int>(color);

    std::cout << "Color value: " << colorValue << std::endl;  // 输出 0

    return 0;
}

 

说明
enum class 的枚举常量必须使用作用域限定符(如 Color::Red)来访问,避免了命名冲突。强类型枚举不隐式转换为整数,增加了类型安全性。

7. 静态断言 (static_assert)

概念
static_assert 是 C++11 引入的编译时断言机制,用于在编译时验证某些条件。它主要用于模板编程或编译期常量表达式验证。

示例

#include <iostream>

template<typename T>
void checkType() {
    static_assert(sizeof(T) == 4, "Type size must be 4 bytes");
}

int main() {
    checkType<int>();  // 正确:int 通常是 4 字节

    // checkType<double>();  // 错误:double 通常不是 4 字节,编译期断言失败

    return 0;
}

 

说明
static_assert 用于编译时检查条件,如果条件不满足,编译器会抛出错误并输出自定义的错误信息。它常用于模板编程中,确保模板参数符合某些要求。

8. 委托构造函数

概念
C++11 允许在一个构造函数中调用另一个构造函数,减少代码重复,简化构造函数的编写。

示例

#include <iostream>

class MyClass {
public:
    MyClass(int value) : value_(value) {
        std::cout << "Constructor with int" << std::endl;
    }

    MyClass() : MyClass(0) {  // 委托构造函数
        std::cout << "Default constructor" << std::endl;
    }

private:
    int value_;
};

int main() {
    MyClass obj1;        // 调用默认构造函数
    MyClass obj2(10);    // 调用带参数的构造函数

    return 0;
}

 

说明
通过委托构造函数,可以在一个构造函数中调用其他构造函数,从而减少代码重复,提高代码质量和可维护性。

9. 继承构造函数

概念
派生类可以直接使用基类的构造函数,简化了派生类构造函数的编写。

示例

#include <iostream>

class Base {
public:
    Base(int value) : value_(value) {
        std::cout << "Base constructor" << std::endl;
    }

private:
    int value_;
};

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

int main() {
    Derived obj(10);  // 调用基类构造函数

    return 0;
}

 

说明
通过使用 using Base::Base;,派生类可以继承基类的构造函数,从而简化构造函数的编写,避免代码冗余。

10. 变长模板参数

概念
C++11 支持变长模板参数(variadic templates),使得模板可以接受任意数量和类型的参数。这极大地增强了模板的灵活性和通用性。

示例

#include <iostream>

template<typename T>
void print(T t) {
    std::cout << t << std::endl;
}

template<typename T, typename... Args>
void print(T t, Args... args) {
    std::cout << t << " ";
    print(args...);  // 递归调用,继续处理剩余的参数
}

int main() {
    print(1, 2.5, "Hello", 'A');  // 输出 1 2.5 Hello A

    return 0;
}

 

说明
... 是变长模板的语法,用于接收不定数量的参数。可以通过递归调用展开参数包,每次处理一个参数。这种特性使得模板编程更加灵活,适用于需要处理多个类型和数量参数的场景。

标准库扩展

1. 智能指针

C++11 引入了智能指针来自动管理资源,避免内存泄漏和手动管理动态内存的复杂性。

1.1 std::unique_ptr

概念
std::unique_ptr 是独占所有权的智能指针,确保一个指针对象只有一个所有者,当它超出作用域时自动释放资源。

示例

#include <iostream>
#include <memory>

int main() {
    std::unique_ptr<int> p1(new int(10));  // 创建 unique_ptr
    std::cout << *p1 << std::endl;  // 输出 10

    // 转移所有权
    std::unique_ptr<int> p2 = std::move(p1);
    std::cout << (p1 ? "p1 not null" : "p1 null") << std::endl;  // 输出 "p1 null"

    return 0;
}

 

说明
std::unique_ptr 不允许拷贝,但可以通过 std::move 转移所有权。离开作用域时会自动释放资源,确保内存不会泄漏。

1.2 std::shared_ptr

概念
std::shared_ptr 是共享所有权的智能指针,多个指针可以指向相同的对象,当所有指针都不再指向该对象时,资源才会被释放。

示例

#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> sp1(new int(20));
    std::shared_ptr<int> sp2 = sp1;  // 共享所有权

    std::cout << "sp1 use count: " << sp1.use_count() << std::endl;  // 输出 2
    std::cout << "sp2 use count: " << sp2.use_count() << std::endl;  // 输出 2

    return 0;
}

 

说明
std::shared_ptr 通过引用计数来管理对象的生命周期,当引用计数为 0 时,资源会被释放。use_count() 函数返回当前有多少个 shared_ptr 指向同一个对象。

2. 多线程支持

C++11 提供了原生的多线程库,使得编写跨平台的多线程程序变得更加简洁。主要包括 std::thread 用于创建线程,std::mutex 用于保护共享数据,以及 std::lock_guardstd::unique_lock 提供简化的锁管理。

2.1 std::thread

概念
std::thread 是 C++11 引入的用于创建和管理线程的类。它允许并行执行任务,提升程序的性能。

示例

#include <iostream>
#include <thread>

// 线程执行的函数
void threadFunction() {
    std::cout << "Hello from thread!" << std::endl;
}

int main() {
    // 创建线程并执行
    std::thread t(threadFunction);

    // 等待线程完成
    t.join();

    return 0;
}

 

说明
std::thread 构造函数接受一个可调用对象(如函数指针、Lambda 表达式、函数对象等)。join() 用于等待线程结束。如果不调用 join()detach(),则程序在析构 std::thread 对象时会崩溃。

2.2 std::mutex 和 std::lock_guard

概念
std::mutex 用于多线程环境中保护共享数据,防止多个线程同时访问同一个资源而导致数据竞争。std::lock_guard 是一种用于管理 mutex 锁的 RAII 风格的工具,简化了加锁和解锁的过程。

示例

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

std::mutex mtx;  // 互斥量用于保护共享数据

void print_message(const std::string& message) {
    std::lock_guard<std::mutex> lock(mtx);  // 自动加锁,作用域结束时自动解锁
    std::cout << message << std::endl;
}

int main() {
    std::thread t1(print_message, "Hello from thread 1");
    std::thread t2(print_message, "Hello from thread 2");

    t1.join();
    t2.join();

    return 0;
}

 

说明
std::mutex 可以保护临界区,防止多个线程同时访问同一数据。std::lock_guard 自动管理锁的获取和释放,避免手动 lock()unlock() 时出错。

3. 原始字面量 (Raw String Literals)

概念
C++11 引入了原始字符串字面量,可以让开发者更加方便地表示包含特殊字符的字符串,避免转义的复杂性。

示例

#include <iostream>

int main() {
    const char* raw_str = R"(Line 1
Line 2
Line 3)";

    std::cout << raw_str << std::endl;

    return 0;
}

 

说明
原始字符串字面量使用 R"( 开头和 )" 结尾,可以包含换行符和特殊字符而无需转义,方便表示复杂字符串。

4. long long 类型

概念
C++11 确保 long long 至少为 64 位,支持 LLll 后缀用于定义长整型,支持 unsigned long long 及其后缀变体。

示例

#include <iostream>

int main() {
    long long big_num = 9223372036854775807LL;
    unsigned long long ubig_num = 18446744073709551615ULL;

    std::cout << "Long long: " << big_num << std::endl;
    std::cout << "Unsigned long long: " << ubig_num << std::endl;

    return 0;
}

 

说明
long long 类型用于表示大整数,确保其至少为 64 位。LLULL 后缀用于声明 long longunsigned long long 常量。

5. 空指针 nullptr

概念
引入 nullptr 取代 NULL,提供了一种类型安全的方式来表示空指针,避免了重载函数时的模糊性。

示例

#include <iostream>

void f(int) {
    std::cout << "Function with int parameter" << std::endl;
}

void f(char*) {
    std::cout << "Function with char* parameter" << std::endl;
}

int main() {
    f(0);        // 调用 f(int)
    f(nullptr);  // 调用 f(char*)

    return 0;
}

 

说明
nullptr 是类型安全的空指针常量,避免了 NULL 在重载函数时的模糊性。使用 nullptr 可以让代码更加清晰和安全。

6. constexpr 关键字

概念
constexpr 用于定义常量表达式,在编译时计算值,提高了性能。与 const 不同,constexpr 确保表达式在编译时求值。

示例

#include <iostream>

// constexpr 函数必须简单,且能在编译时计算结果
constexpr int square(int x) {
    return x * x;
}

int main() {
    constexpr int val = square(5);  // 在编译时计算出 val = 25
    int arr[val];  // 数组大小为 25

    std::cout << "Square of 5 is: " << val << std::endl;  // 输出 Square of 5 is: 25

    return 0;
}

 

说明
constexpr 可以用于函数和变量。它要求函数体必须非常简单,以确保在编译时能完全执行。在编译时计算的值可以用于数组大小、模板参数等。

7. final 和 override 关键字

概念
final 用于防止类被继承或虚函数被重写,override 用于确保派生类的方法确实是重写基类的虚函数。

示例

#include <iostream>

class Base {
public:
    virtual void show() const {
        std::cout << "Base show" << std::endl;
    }
};

class Derived : public Base {
public:
    void show() const override {  // 确保是重写基类的方法
        std::cout << "Derived show" << std::endl;
    }

    void display() final {  // 防止进一步重写
        std::cout << "Derived display" << std::endl;
    }
};

class FurtherDerived : public Derived {
public:
    // void display() override;  // 编译错误:不能重写 final 方法
};

int main() {
    Base* b = new Derived();
    b->show();  // 调用 Derived 的 show 方法
    delete b;

    return 0;
}

 

说明
override 关键字确保派生类的方法确实是重写基类的虚函数,否则编译器会报错。final 关键字防止类被继承或虚函数被进一步重写。

8. 模板的优化

概念
C++11 对模板的使用进行了许多优化,使得模板编程更加灵活高效。例如,变长模板参数、decltypeauto 等新特性都大大增强了模板的表达能力。

示例

#include <iostream>

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

int main() {
    std::cout << add(1, 2.5) << std::endl;  // 输出 3.5
    std::cout << add(std::string("Hello "), "World!") << std::endl;  // 输出 Hello World!

    return 0;
}

​​​​​​​

说明
通过使用 decltypeauto,模板函数可以更加灵活地处理不同类型的参数,并自动推导返回类型,提高了代码的通用性和可维护性。

9. 自动推导 decltype

概念
decltype 用于在编译时获取表达式的类型,不会计算表达式的值。

示例

#include <iostream>

int main() {
    int x = 10;
    decltype(x) y = x + 5;  // y 的类型是 int

    std::cout << "y = " << y << std::endl;  // 输出 y = 15

    return 0;
}

 

说明
decltype 关键字在编译时推导出表达式的类型,可以用于声明变量的类型,而不需要显式指定类型。

10. using 的使用

概念
using 关键字提供了比 typedef 更加清晰的别名声明方式,尤其在定义模板时尤为方便。

示例

#include <iostream>
#include <vector>

// 使用 typedef 定义别名
typedef std::vector<int> IntVector;

// 使用 using 定义别名
using IntList = std::vector<int>;

int main() {
    IntVector vec = {1, 2, 3};
    IntList lst = {4, 5, 6};

    for (auto i : vec) {
        std::cout << i << " ";  // 输出 1 2 3
    }
    std::cout << std::endl;

    for (auto i : lst) {
        std::cout << i << " ";  // 输出 4 5 6
    }
    std::cout << std::endl;

    return 0;
}

 

说明
using 关键字可以替代 typedef,定义类型别名时更加直观和清晰,特别是在定义模板别名时非常有用。

编译器功能改进

1. 静态断言 (static_assert)

概念
static_assert 是 C++11 引入的编译时断言机制,用于在编译时验证某些条件。它主要用于模板编程或编译期常量表达式验证。

示例

#include <iostream>

template<typename T>
void checkType() {
    static_assert(sizeof(T) == 4, "Type size must be 4 bytes");
}

int main() {
    checkType<int>();  // 正确:int 通常是 4 字节

    // checkType<double>();  // 错误:double 通常不是 4 字节,编译期断言失败

    return 0;
}

 

说明
static_assert 用于编译时检查条件,如果条件不满足,编译器会抛出错误并输出自定义的错误信息。它常用于模板编程中,确保模板参数符合某些要求。

2. 强制枚举 (enum class)

概念
C++11 引入了强类型枚举 enum class,与传统枚举相比,它具有更好的类型安全性。传统的 enum 会将枚举常量提升为整数,而 enum class 则不会自动转换为整数,避免了类型不安全的隐患。

示例

#include <iostream>

enum class Color { Red, Green, Blue };
enum class Fruit { Apple, Orange, Banana };

int main() {
    Color color = Color::Red;
    Fruit fruit = Fruit::Apple;

    // 错误:不能隐式转换 enum class 类型
    // int colorValue = color;

    // 正确:显式转换为整数
    int colorValue = static_cast<int>(color);

    std::cout << "Color value: " << colorValue << std::endl;  // 输出 0

    return 0;
}

 

说明
enum class 的枚举常量必须使用作用域限定符(如 Color::Red)来访问,避免了命名冲突。强类型枚举不隐式转换为整数,增加了类型安全性。

3. noexcept 规范

概念
noexcept 关键字用于指明一个函数不会抛出异常,有助于编译器进行优化。

示例

#include <iostream>

void func() noexcept {
    std::cout << "This function is noexcept" << std::endl;
}

int main() {
    func();

    return 0;
}

 

说明
使用 noexcept 关键字指明函数不会抛出异常,可以帮助编译器进行优化,并提供更多的安全保障。

小结

C++11 标准是对 C++ 语言的一个重要改进,带来了大量的新特性,提升了语言的可用性、表达能力和效率。通过对这些新特性的深入学习与实践,能够编写出更加简洁、高效、安全的代码。

  • 类型推导 (auto) 简化了变量声明,减少了冗余。
  • Lambda 表达式 提供了简洁的函数表达方式,提升了代码的灵活性。
  • 右值引用与移动语义 优化了资源管理,提高了性能。
  • 基于范围的 for 循环 提供了简洁的容器迭代方式。
  • 列表初始化 提供了统一而简洁的初始化语法。
  • 智能指针 提供了安全的内存管理机制,防止内存泄漏。
  • 多线程支持 提供了跨平台的多线程编程能力。
  • 强类型枚举 (enum class) 提供了更好的类型安全性。
  • 静态断言 (static_assert) 提供了编译时的条件检查。
  • constexpr 提供了编译时的常量表达式计算。
  • final 和 override 提供了更好的代码控制和安全性。
  • 变长模板参数 增强了模板的灵活性。
  • decltype 和 using 提高了代码的可读性和可维护性。

通过学习和掌握这些新特性,开发者可以更好地利用 C++11 的强大功能编写出更加高效和稳定的代码。

 

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿享天开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值