开发者

C++11范围for初始化列表auto decltype详解

开发者 https://www.devze.com 2025-07-29 10:38 出处:网络 作者: QQ_437664314
目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3.1 内置类型3.2 自定义类型对于自定义类4. 范围 for5. 智能指针总结C++11新特性
目录
  • C++11新特性
    • 1. 自动类型推导auto
      • 1.1 基本语法
    • 2. decltype
      • 3. 列表初始化
        • 3.1 内置类型
        • 3.2 自定义类型
        • 对于自定义类
      • 4. 范围 for
        • 5. 智能指针
        • 总结

          C++11新特性

          1. 自动类型推导auto

          `在C++98中auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以auto就没什么价值了。

          C++11中废弃auto原来的用法,将其用于实现自动类型腿断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型。

          1.1 基本语法

          auto i = 42;        // i 是 int
          auto d = 3.14;      // d 是 double
          auto s = "hello";   // s 是 const char*
          auto v = {1, 2, 3}; // v 是 std::initializer_list<int>
          const auto ci = i;     // const int
          auto& ri = i;          // int&
          

          2. decltype

          关键字decltype将变量的类型声明为表达式指定的类型。

          // decltype 可以推导出参数类型,并进行传递
          vector<decltype(it)>v1;
          

          decltypeauto方便的一点是decltype无需显式实例化,也就是单纯定义也行decltype还可以作为模板参数传递,而auto不行。

          3. 列表初始化

          ​ 在 C++11 中,初始化列表(使用花括号 {})为内置js类型和自定义类型的初始化提供了统一、安全的语法。下面一一列举。

          • 初始化列表 {} 是 C++11后 的推荐方式,提供类型安全语法统一性
          • 构造函数初始化 () 保留传统行为,但在某些场景(如 STL 容器)可能产生歧义。

          3.1 内置类型

          int main(){
              int a{ 5 };     // 直接初始化
              int b = { 10 }; // 拷贝初始化
              char g{ 'A' };  // 正确,但不能超过char范围
          
              int* ptr1{};   // 初始化为空指针
              int* ptr2{ &a }; // 指向变量a
          
              int arr1[]{ 1, 2, 3 };  // 自动推导大小
              int arr2[5]{ 1, 2, 3 }; // 部分初始化,剩余元素为0
              char str[]{ "Hello" };  // 字符数组
          
              std::cout << "ptr1: " << ptr1 << "\n"
                  << "ptr2: " << ptr2 << "\n"
                  << "str: " << str << std::endl;
              return 0;
          }
          

          C++11范围for初始化列表auto decltype详解

          其实就是当内置类型使用 { }初始化时,实际上是在调用它的构造函数进行构造这就不奇怪了,无非就是让内置类型将 { } 也看做一种特殊的构造:构造+赋值 优化为直接构造我们可以通过一个简单的Datw类来体现这一现象。

          class Date {
          public:
              Date(int y,int m,int d):_year(y),_month(m),_day(d){}
          private:
              int _year;
              int _month;
              jsint _day;
          };
          int main(){
              Date d1 = { 0,1,1 };
              return 0;
          }
          

          此时可以直接通过列表初始化{}初始化这个类。在C++11中允许省略=符号,编译无报错,使其与拷贝构造函数一样。使用关键字·explicit·可以避免编译器隐式转换。

          C++11范围for初始化列表auto decltype详解

          这样编译器无法优化,便无法对d1进行构造,自然无法完成赋值。d2相当于直接拷贝构造函数。

          即对于内置类型来说,列表初始化 { } 实际上就相当于调用了内置类型的构造函数,构造出来一个对象。

          3.2 自定义类型

          C++11之前对于自定义类型初始化比较复杂,例如vector需要循环插入,在c++11时使用初始化列表对于自定义类型的数据操作更加方便。

          C++11范围for初始化列表auto decltype详解

          3.2.1 初始化列表赋值底层

          对于STL容器:

          STL容器(如 vectormapset 等)重载了 operator= 以支持 std::initializer_list,因此,可以直接用 {} 赋值:

          std::vector<int>& operator=(std::initializer_list<int> il);
          
          map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
          std::vect编程or<int> v;
          v = {1, 2, 3};  // 调用 operator=(initializer_list<int>)
          

          对于自定义类

          如果类定义了 operator= 接受 std::initializer_list,则可以使用 {} 赋值:让模拟实现的vector也支持{}初始化和赋值…

          template <class T>
                  class vector{
                  public:
                      typedef T *iterator;
                      vector(initializer_list<T> l){
                          _start = new T[l.size()];
                          _finish = _start + l.size();
                          _endofstorage = _start + l.size();
                          iterator vit = _start;
                          typename initializer_list<T>::iterator lit = l.begin();
                          while (lit != l.end()){
                              *vit++ = *lit++;
                          }
                      }
                      vector<T> &operator=(initializer_list<T> l){
                          vector<T> tmp(l);
                          std::swap(_start, tmp._start);
                          std::swap(_finish, tmp._f编程inish);
                          std::swapwww.devze.com(_endofstorage, tmp._endofstorage);
                          return *this;
                      }
                  private:
                      iterator _start;
                      iterator _finish;
                      iterator _endofstorage;
                  };
          
          • 同时提供普通构造函数和 initializer_list 构造函数时,注意优先级差异。

          4. 范围 for

          其为C++11引入的一种简化容器遍历的语法,它使遍历序列容器(如数组、vector、list 等)变得更加简洁直观。

          基本语法:

          for (类型 变量名 : 目标序列) {
              // 循环体
          }
          

          如果需要修改容器中的元素,需要使用引用,这样能够避免发生数据拷贝影响效率。同时使用const修饰能够避免修改原始对象。

          std::vector<std::string> words = {"aaaa", "bbbb", "cccc"};
          for (const auto& word : words) {//使用 & 避免拷贝,使用const避免原始数据被修改
              std::cout << word << " ";
          }
          // 输出:aaaa bbbb cccc
          

          5. 智能指针

          bbb", “cccc”};
          for (const auto& word : words) {//使用 & 避免拷贝,使用const避免原始数据被修改
          std::cout << word << " ";
          }
          // 输出:aaaa bbbb cccc

          总结

          以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

          0

          精彩评论

          暂无评论...
          验证码 换一张
          取 消

          关注公众号