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

相关文章

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

SQL Server 中的 WITH (NOLOCK) 示例详解

《SQLServer中的WITH(NOLOCK)示例详解》SQLServer中的WITH(NOLOCK)是一种表提示,等同于READUNCOMMITTED隔离级别,允许查询在不获取共享锁的情... 目录SQL Server 中的 WITH (NOLOCK) 详解一、WITH (NOLOCK) 的本质二、工作

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (

Java Thread中join方法使用举例详解

《JavaThread中join方法使用举例详解》JavaThread中join()方法主要是让调用改方法的thread完成run方法里面的东西后,在执行join()方法后面的代码,这篇文章主要介绍... 目录前言1.join()方法的定义和作用2.join()方法的三个重载版本3.join()方法的工作原

Spring AI使用tool Calling和MCP的示例详解

《SpringAI使用toolCalling和MCP的示例详解》SpringAI1.0.0.M6引入ToolCalling与MCP协议,提升AI与工具交互的扩展性与标准化,支持信息检索、行动执行等... 目录深入探索 Spring AI聊天接口示例Function CallingMCPSTDIOSSE结束语

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编

PyTorch中的词嵌入层(nn.Embedding)详解与实战应用示例

《PyTorch中的词嵌入层(nn.Embedding)详解与实战应用示例》词嵌入解决NLP维度灾难,捕捉语义关系,PyTorch的nn.Embedding模块提供灵活实现,支持参数配置、预训练及变长... 目录一、词嵌入(Word Embedding)简介为什么需要词嵌入?二、PyTorch中的nn.Em

Python Web框架Flask、Streamlit、FastAPI示例详解

《PythonWeb框架Flask、Streamlit、FastAPI示例详解》本文对比分析了Flask、Streamlit和FastAPI三大PythonWeb框架:Flask轻量灵活适合传统应用... 目录概述Flask详解Flask简介安装和基础配置核心概念路由和视图模板系统数据库集成实际示例Stre

Spring Bean初始化及@PostConstruc执行顺序示例详解

《SpringBean初始化及@PostConstruc执行顺序示例详解》本文给大家介绍SpringBean初始化及@PostConstruc执行顺序,本文通过实例代码给大家介绍的非常详细,对大家的... 目录1. Bean初始化执行顺序2. 成员变量初始化顺序2.1 普通Java类(非Spring环境)(

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么