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

2025-07-28 20:50

本文主要是介绍C++11范围for初始化列表auto decltype详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效...

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.chinasem.cn(_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

总结

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

这篇关于C++11范围for初始化列表auto decltype详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155516

相关文章

Redis 的 SUBSCRIBE命令详解

《Redis的SUBSCRIBE命令详解》Redis的SUBSCRIBE命令用于订阅一个或多个频道,以便接收发送到这些频道的消息,本文给大家介绍Redis的SUBSCRIBE命令,感兴趣的朋友跟随... 目录基本语法工作原理示例消息格式相关命令python 示例Redis 的 SUBSCRIBE 命令用于订

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

SpringBoot日志级别与日志分组详解

《SpringBoot日志级别与日志分组详解》文章介绍了日志级别(ALL至OFF)及其作用,说明SpringBoot默认日志级别为INFO,可通过application.properties调整全局或... 目录日志级别1、级别内容2、调整日志级别调整默认日志级别调整指定类的日志级别项目开发过程中,利用日志

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

MySQL8 密码强度评估与配置详解

《MySQL8密码强度评估与配置详解》MySQL8默认启用密码强度插件,实施MEDIUM策略(长度8、含数字/字母/特殊字符),支持动态调整与配置文件设置,推荐使用STRONG策略并定期更新密码以提... 目录一、mysql 8 密码强度评估机制1.核心插件:validate_password2.密码策略级

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

详解python pycharm与cmd中制表符不一样

《详解pythonpycharm与cmd中制表符不一样》本文主要介绍了pythonpycharm与cmd中制表符不一样,这个问题通常是因为PyCharm和命令行(CMD)使用的制表符(tab)的宽... 这个问题通常是因为PyCharm和命令行(CMD)使用的制表符(tab)的宽度不同导致的。在PyChar

sky-take-out项目中Redis的使用示例详解

《sky-take-out项目中Redis的使用示例详解》SpringCache是Spring的缓存抽象层,通过注解简化缓存管理,支持Redis等提供者,适用于方法结果缓存、更新和删除操作,但无法实现... 目录Spring Cache主要特性核心注解1.@Cacheable2.@CachePut3.@Ca