本文主要是介绍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;
decltype
比auto
方便的一点是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; }
其实就是当内置类型使用 { }
初始化时,实际上是在调用它的构造函数进行构造这就不奇怪了,无非就是让内置类型将 { }
也看做一种特殊的构造:构造+赋值
优化为直接构造我们可以通过一个简单的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·可以避免编译器隐式转换。
这样编译器无法优化,便无法对d1
进行构造,自然无法完成赋值。d2
相当于直接拷贝构造函数。
即对于内置类型来说,列表初始化 { }
实际上就相当于调用了内置类型的构造函数,构造出来一个对象。
3.2 自定义类型
C++11之前对于自定义类型初始化比较复杂,例如vector
需要循环插入,在c++11
时使用初始化列表对于自定义类型的数据操作更加方便。
3.2.1 初始化列表赋值底层
对于STL容器:
STL
容器(如 vector
、map
、set
等)重载了 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
总结
这篇关于C++11范围for初始化列表auto decltype详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!