C++进阶 —— 列表初始化(C++11新特性)

目录

一,列表初始化

二,类列表初始化

三,类模板列表初始化

库模板初始化列表实现

模拟模板初始化列表实现


        在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称;不过由于TC1主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯的把两个标准合称为C++98/03标准;从C++0x到C++11,C++标准十年磨一剑,第二个真正意义上的标准姗姗来迟; 相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言;相比较而言,C++11能更好地用于系统开放和库开发,语法更加泛化和简单化,更加稳定和安全,不仅功能强大,而且能提升程序员的开发效率;

一,列表初始化

        列表初始化是一种 C++11 中引入的新特性,可用来初始化各种类型的对象,包括数组、结构体、类以及容器等。具体来说,列表初始化使用花括号 {} 将一组值括起来,用逗号分隔各个元素,形成一个初始化列表;

{ }初始化

        在C++98中,标准允许使用{}对数组元素进行统一的列表初始化设定;但对一些自定义类型不可这样使用,无法编译,导致每次定义vector时,都需要先定义vector,在循环对其赋初始值,非常不方便;

int arr[] = {1, 2, 3, 4, 5};
int arr[5] = {0};
//c++98中不可这样使用,需循环赋值
vector v = {1, 2, 3, 4, 5};

        C++11扩大了用大括号{}括起来的列表(初始化)的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加;

编译器会对大括号中的元素进行类型检查,不符合要求即报错;

  • 元素类型与被初始化对象类型匹配;
  • 对自定义类型大括号内的元素个数与被初始化对象构造函数参数个数匹配;
//内置类型
int x = 10;
int x = {10};
int x{10};

int x = 1+2;
int x = {1+2};
int x{1+2};

//数组
int arr[5] = {1,2,3,4,5};
int arr[] = {1,2,3,4,5};
int arr[]{1,2,3,4,5};

//动态数组,C++98不支持
int* parr = new int[5]{1,2,3,4,5};
int* parr = new int[]{1,2,3,4,5};

//标准容器
vector v1{ 1, 2, 3, 4, 5 };
vector v2={ 1, 2, 3, 4, 5 };
map m{{1,1},{2,2},{3,3},{4,4}};

二,类列表初始化

  • 编译器尝试匹配构造函数,该构造函数参数列表与大括号内元素个数一致;
class Point
{
public:
	Point(int x=0,int y=0)
		:_x(x)
		,_y(y)
	{}
private:
	int _x;
	int _y;
};

int main()
{
    //以下等价
	Point p(1, 2);
	Point p1 = { 1, 2 };   
    Point p2{ 1, 2 };
}

C++进阶 —— 列表初始化(C++11新特性)_第1张图片

三,类模板列表初始化

  • 要支持列表初始化,需给该类(模板类)添加一个带有initializer_list类型参数的构造函数;
  • initialier_list是系统自定义的类模板,该类模板中主要有三个方法,begin()、end()迭代器,以及获取区间中元素个数的方法size();
//库定义
template 
class initializer_list 
{
public:
    ...
    constexpr initializer_list() noexcept : _First(nullptr), _Last(nullptr) {}
    constexpr initializer_list(const _Elem* _First_arg, const _Elem* _Last_arg) noexcept
        : _First(_First_arg), _Last(_Last_arg) {}
    _NODISCARD constexpr const _Elem* begin() const noexcept {return _First;}
    _NODISCARD constexpr const _Elem* end() const noexcept {return _Last;}
    _NODISCARD constexpr size_t size() const noexcept {return static_cast(_Last - _First);}
private:
    const _Elem* _First;
    const _Elem* _Last;
};

库模板初始化列表实现

  • 调用对应的初始化列表构造函数;
  • 然后将初始化列表值循环赋值对象;
//vector库模板,初始化列表构造函数	
_CONSTEXPR20_CONTAINER vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc())
	: _Mypair(_One_then_variadic_args_t{}, _Al)
{
	auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal());
	_Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2);
    //初始化列表赋值
	_Range_construct_or_tidy(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{});
	_Proxy._Release();
}

template 
_CONSTEXPR20_CONTAINER void _Range_construct_or_tidy(_Iter _First, _Iter _Last, input_iterator_tag) {
	_Tidy_guard _Guard{ this };
	for (; _First != _Last; ++_First) {
		emplace_back(*_First); // performance note: emplace_back()'s strong guarantee is unnecessary here
	}
	_Guard._Target = nullptr;
}

模拟模板初始化列表实现

#include
template
class MyVector
{
public:
	MyVector(std::initializer_list lt)
		:_capacity(lt.size())
		,_size(0)
	{
		_array = new T[_capacity];
		for (auto e : lt)
			_array[_size++] = e;
	}
	
	MyVector& operator=(std::initializer_list lt)
	{
		delete[] _array;
		size_t i = 0;
		for (auto e : lt)
			_array[i++] = e;
		return *this;
	}
private:
	T* _array;
	size_t _capacity;
	size_t _size;
};

int main()
{
    //以下三种形式等价
    MyVector v1({ 1,2,3 });
	MyVector v2 = { 1,2,3 };
	MyVector v3{ 1,2,3 };
    //调用operator=
	v1 = { 3,2,1 };
	return 0;
}

你可能感兴趣的:(#,C++,编程语言,c++)