2 - 初始化列表initializer_list
在学习函数模板之前,先看看初始化列表initializer_list
。
介绍
就是初始化列表,在<initializer_list>
中被定义,可以用它来初始化各种容器,例如vector
,数组
等。
使用
初始化容器
// 左值初始化
std::initializer_list<int> iList{ 1, 2, 3, 4, 5 };
std::vector<int> iVec(iList);
// 右值初始化
std::vector<int> iVec2 = { 1, 2, 3, 4, 5 };
作为函数参数
以上篇文章中的类模板为例,新建构造函数:
// 左值和右值版本
template<typename T>
MyArray<T>::MyArray(const std::initializer_list<T>& list)
{
if (list.size())
{
unsigned length = 0;
data = new T[list.size()]();
// 用萃取技术判断是不是指针类型,防止浅拷贝
if (std::is_pointer<T>::value)
{
for (auto elem : list)
{
// 用模板特化技术判断是什么类型的指针
data[length++] = new typename get_type<T>::type(*elem);
}
}
else
{
for (const auto& elem : list)
{
data[length++] = elem;
}
}
}
else
{
data = nullptr;
}
}
template<typename T>
MyArray<T>::MyArray(std::initializer_list<T>&& list)
{
if (list.size())
{
unsigned length = 0;
data = new T[list.size()]();
for (const auto& elem : list)
{
data[length++] = elem;
}
}
else
{
data = nullptr;
}
}
记得添加以下内容,突然多了萃取技术跟模板特化有点懵:
// 萃取技术
#include <type_traits>
// 模板特化(解决从int*知道是int类型的指针)
template<typename T>
struct get_type
{
using type = T;
};
template<typename T>
struct get_type<T*>
{
using type = T;
};
然后就能在main函数中使用了:
int i1 = 10;
int i2 = 20;
std::initializer_list<int*> iList{ &i1, &i2 };
MyArray<int*> arrayPi1(iList);
MyArray<int*> arrayPi2(std::move(iList));
for (unsigned i = 0; i < 2; i++)
{
std::cout << *arrayPi1[i] << std::endl;
std::cout << *arrayPi2[i] << std::endl;
}
注意:这里出现了内存泄漏,原因是类型为int*
,导致没有把二次指针的内存给释放掉。如果使用智能指针/容器(vector)的话就好了。
参考资料
- 飘零的落花 - 现代C++详解
- C++20高级编程