【C++11】新特性

前言:

C++11 C++编程语言的一个重要版本,于2011年发布。它带来了数量可观的变化,包含约 140 个新特性,以及对 C++03 标准中约600个缺陷的修正,更像是从 C++98/03 中孕育出的新语言

列表初始化

C++11 中的列表初始化(List Initialization)是一种新的初始化语法,它提供了更统一、更灵活和更安全的初始化方式。以下是关于 C++11 列表初始化的详细介绍

基本语法

可以直接在变量名后面加上初始化列表来进行对象的初始化。

cpp 复制代码
int x = {10};  // 初始化一个整数变量 x 为 10
int arr[] = {1, 2, 3};  // 初始化一个整数数组 arr
std::vector<int> v = {4, 5, 6};  // 初始化一个 std::vector 容器

适用范围

  • **内置类型:**可用于所有内置类型,如整数、浮点数、字符等。
  • **自定义类型:**对于自定义的类或结构体,如果满足聚合类型的条件,也可以使用列表初始化。如果类定义了合适的构造函数(包括接受 std::initializer_list 类型参数的构造函数),同样可以使用列表初始化

聚合类型的条件

在 C++11 中,聚合类型需要满足以下条件1:

  • 类型是一个普通数组 :如 int[5]char[]double[3] 等。
  • 类型是一个类,且满足以下条件:
    • 没有用户声明的构造函数。
    • 没有用户提供的构造函数(允许显示预置或弃置的构造函数)。
    • 没有私有或保护的非静态数据成员。
    • 没有基类。
    • 没有虚函数。
    • 没有 {}= 直接初始化的非静态数据成员。
    • 没有默认成员初始化器

initializer_list

initializer_list C++11 引入的一种模板类,用于表示某种类型的对象的列表。它提供了一种方便的方式来处理和传递一组相同类型的值,类似于其他语言中的列表或数组。以下是关于 initializer_list 的一些重要特点和用法:

  • 创建和初始化

    • 可以使用花括号 {} 来创建一个 std::initializer_list 对象,并在其中列出要包含的元素。例如:std::initializer_list<int> myList = {1, 2, 3, 4, 5};
    • 元素的类型必须相同,否则会导致编译错误。不过,编译器会进行一些隐式的类型转换,例如将 int 类型的元素转换为 double 类型的列表是允许的,但可能会有精度损失。例如:std::initializer_list<double> doubleList = {1, 2, 3}; 这里 123 会被隐式转换为 1.02.03.0
    • 不允许进行缩窄转换,即会导致数据丢失或精度降低的转换是不被允许的。例如:std::initializer_list<char> charList = {1000}; 会导致编译错误,因为 1000 超出了 char 类型的取值范围。
  • 常见用法

    • 初始化容器 :可以方便地用于初始化标准库中的容器,如 std::vectorstd::list 等。例如:std::vector<int> vec = {1, 2, 3};
    • 函数参数 :函数可以接受 std::initializer_list 作为参数,从而可以接收任意数量的同类型参数。例如:
    cpp 复制代码
    void printValues(std::initializer_list<int> values) {
        for (auto value : values) {
            std::cout << value << " ";
        }
        std::cout << std::endl;
    }
    
    int main() {
        printValues({1, 2, 3, 4, 5});
        return 0;
    }
    • 类的构造函数:在类的构造函数中使用 std::initializer_list,可以方便地实现多种初始化方式。例如:

auto

C++11 中,auto是一个用于自动类型推导的关键字。它可以让编译器根据初始化表达式的类型自动推断变量的类型,从而简化代码的编写,提高代码的可读性和可维护性1。以下是关于 auto 的一些重要特点和用法:

  • 基本用法 :在定义变量时,使用 auto 关键字,编译器会根据初始化的值来推断变量的类型。例如:
cpp 复制代码
auto x = 5;  // x 的类型为 int
auto y = 3.14;  // y 的类型为 double
auto z = "hello, world!";  // z 的类型为 const char*

与指针和引用结合

  • auto 可以与指针结合使用,用于自动推导指针类型。例如:
cpp 复制代码
int num = 10;
auto ptr = &num;  // ptr 的类型为 int*
  • 用于函数返回值类型推导(C++14) :在 C++14 标准中,可以使用 auto 关键字结合 -> 运算符来推导函数的返回值类型。例如:
cpp 复制代码
auto add(int a, int b) -> int {
    return a + b;  // 返回 a 和 b 的和
}
  • 在范围 for 循环中的应用(C++11) :C++11 引入的范围 for 循环结合 auto 关键字,可以更方便地遍历容器。例如:
cpp 复制代码
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (auto number : numbers) {
    std::cout << number << std::endl;  // 输出每个元素
}

优点

  • 简化代码 :避免了手动指定复杂的类型,尤其是对于模板库中复杂的迭代器类型等,使用 auto 可以大大简化代码的书写1。
  • 提高可读性:使代码更加清晰易读,减少了类型声明带来的视觉干扰,让开发者更关注于代码的逻辑而不是类型的细节1。
  • 灵活性 :在类型需要改变时,只需要修改初始化表达式的类型,而使用 auto 定义的变量的类型会自动随之改变,减少了代码修改的工作量。

decltype

基本语法

cpp 复制代码
decltype(expression) variable_name;
  • expression:用于推导类型的表达式。
  • variable_name:根据推导出的类型声明的变量名。

使用场景

  1. 推导变量的类型

    通过 decltype,你可以推导一个已有变量的类型:

    cpp 复制代码
    int a = 5;
    decltype(a) b = 10; // b的类型是int,和a相同
  2. 推导表达式的类型
    decltype 也可以用于推导更复杂的表达式的类型:

    cpp 复制代码
    int x = 10;
    decltype(x + 1.0) y;  // y的类型是double,因为x+1.0的结果是double
  3. 用于函数返回类型

    在C++11中,你可以通过 decltype 根据函数内部表达式来指定返回类型:

    cpp 复制代码
    template<typename T1, typename T2>
    auto add(T1 a, T2 b) -> decltype(a + b) {
        return a + b;
    }

    这里,decltype(a + b) 将推导出 a + b 的类型,并用作返回类型。

  4. 在lambda表达式中使用

    在C++11中,你可以在lambda表达式中使用 decltype 推导捕获变量或返回值的类型:

    cpp 复制代码
    auto lambda = [](int x, int y) -> decltype(x + y) {
        return x + y;
    };

decltype与auto的区别

  • auto 用于根据初始化表达式推导变量类型。
  • decltype 不需要初始化,直接根据表达式推导类型,可以用于声明变量、函数返回类型等。

例如:

cpp 复制代码
int a = 5;
auto b = a;  // auto推导b为int
decltype(a) c;  // decltype推导c为int,但c未初始化

用于根据初始化表达式推导变量类型。

  • decltype 不需要初始化,直接根据表达式推导类型,可以用于声明变量、函数返回类型等。

例如:

cpp 复制代码
int a = 5;
auto b = a;  // auto推导b为int
decltype(a) c;  // decltype推导c为int,但c未初始化

decltype 可以在编译时推导任意表达式的类型,因此在模板和泛型编程中,decltype 是一个强大的工具。

相关推荐
小李不想输啦3 小时前
什么是微服务、微服务如何实现Eureka,网关是什么,nacos是什么
java·spring boot·微服务·eureka·架构
张铁铁是个小胖子3 小时前
微服务学习
java·学习·微服务
ggs_and_ddu3 小时前
Android--java实现手机亮度控制
android·java·智能手机
敲代码娶不了六花4 小时前
jsp | servlet | spring forEach读取不了对象List
java·spring·servlet·tomcat·list·jsp
Yhame.4 小时前
深入理解 Java 中的 ArrayList 和 List:泛型与动态数组
java·开发语言
编程之路,妙趣横生4 小时前
list模拟实现
c++
是小崔啊6 小时前
开源轮子 - EasyExcel02(深入实践)
java·开源·excel
mazo_command6 小时前
【MATLAB课设五子棋教程】(附源码)
开发语言·matlab
myNameGL6 小时前
linux安装idea
java·ide·intellij-idea
IT猿手6 小时前
多目标应用(一):多目标麋鹿优化算法(MOEHO)求解10个工程应用,提供完整MATLAB代码
开发语言·人工智能·算法·机器学习·matlab