[C++11]统一的数据初始化方式 - 初始化列表

Posted Wecccccccc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C++11]统一的数据初始化方式 - 初始化列表相关的知识,希望对你有一定的参考价值。

关于C++中的变量,数组,对象等都有不同的初始化方法,在这些繁琐的初始化方法中没有任何一种方式适用于所有的情况。为了统一初始化方式,并且让初始化行为具有确定的效果,在C++11中提出了列表初始化的概念。

代码如下:

#include<iostream>
#include <string>
using namespace std;

class Person
{
public:
	Person (int a):age(a){}
	Person (int a,string b):age(a),name(b){}

	int getAge()
	{
		return age;
	}

	string getName()
	{
		return name;
	}

private:

	int age;
	string name;
};

int main()
{
	Person p{ 23 };
	cout << p.getAge() << endl;
	Person p1{ 24,"Tom" };
	cout << "name = " << p1.getName() << " age = " << p1.getAge() << endl;
	int a{ 23 };
	cout << a << endl;
	int b = { 24 };
	cout << b << endl;
	int array[] = { 1,2,3,4,5 };
	int *ptr = new int{ 250 };
	cout << *ptr << endl;
	int *array01 = new int[3]{ 1,2,3 };
	double c = double{ 23.12 };//看起来更加直观
	cout << c << endl;
	return 0;
}

测试结果:

在这里插入图片描述

使用初始化列表初始化聚合类型的变量

聚合类型:

1.普通数组本身可以看做是一个聚合类型。

#include <iostream>
#include <string>
using namespace std;

int main()
{
	int x[] = { 1,2,3,4,5 };
	double y[3][3] = { {1.1,2.2,3.3},{4.4,5.5,6.6},{7.7,8.8,9.9} };
	char carry[] = { 'a','b','c','d' };
	string sarry[] = { "hello","world","shijie" };

	return 0;
}

满足以下条件的类(class,struct,union)可以被看做是一个聚合类型:

1.无用户自定义的构造函数

2.无私有或保护的非静态数据成员

场景1:类中有私有成员,无法使用初始化列表初始化

代码如下:

struct T1
{
	int x;
	long y;
protected:
	int z;
}t{1,100,2};//error,类中有私有成员,无法使用初始化列表初始化

场景2:类中有静态成员可以使用初始化列表,但初始化列表不能初始化静态成员变量

代码如下:

struct T2
{
	int x;
	long y;
protected:
	static int z;
}t{1,100,2};//error

结构体中的静态变量z不能使用初始化列表进行初始化,它的初始化遵循静态成员的初始化方式。

代码如下:

struct T2
{
	int x;
	long y;
protected:
	static int z;
}t{113,2312};

int T2::z = 3;

3.无基类
4.无虚函数
5.类中不能有使用{}和 = 直接初始化的非静态数据成员(从C++14就开始支持了)

代码如下:

#include <iostream>
using namespace std;

struct T3
{
public:
	int a = 5;
	int array[3]{ 1,2,3 };
	int c;
};

int main()
{
	T3 t{ 11,{2,3,4},12 };//从C++14开始支持了
	cout << t.a << " " << t.c << endl;
	for (int i = 0; i < 3; i++)
	{
		cout << t.array[i] << " ";
	}
	cout << endl;
	return 0;
}


测试结果:

在这里插入图片描述

使用初始化列表初始化非聚合类型的对象

对于非聚合类,我们必须提供一个对应的构造函数,才能用初始化列表对其初始化。

代码如下:

#include <iostream>
#include <string>
using namespace std;

class Person
{
public:

private:
	int age;
	string name;
};

int main()
{
	Person p{ 18,"Tom" };//error
	return 0;
}

测试结果:

在这里插入图片描述
代码如下:

#include <iostream>
#include <string>
using namespace std;

class Person
{
public:
	Person(int a,string b):age(a),name(b){}

	int getAge()
	{
		return age;
	}

	string getName()
	{
		return name;
	}
	
Person getPerson()
	{
		return { 12,"Jack" };//OK
	}

private:
	int age;
	string name;
};

int main()
{
	Person p{ 18,"Tom" };//OK
	cout << p.getAge() << " " << p.getName() << endl;
	return 0;
}

测试结果:

在这里插入图片描述

注意:
聚合类型的定义并非递归的,也就是说当一个类的非静态成员是非聚合类型时,这个类也可能是聚合类型。

代码如下:

#include <iostream>
using namespace std;

struct T1
{
	int x;
	double y;
private:
	int z;
};

struct T2
{
	T1 t1;
	long x;
	double y;
};

int main()
{
	T2 t2{ {},520,13.14 };
	return 0;
}

可以看到,T1并非一个聚合类型,因为它有一个private的非静态成员,但是尽管T2有一个非聚合类型的非静态成员t1,T2依然是一个聚合类型,可以直接使用初始化列表。

最后强调一下t2对象的初始化过程,对于非聚合类型的成员t1做初始化的时候,可以直接写一对空的{},这相当于调用是T1的无参构造函数。

以上是关于[C++11]统一的数据初始化方式 - 初始化列表的主要内容,如果未能解决你的问题,请参考以下文章

C++11新特性:19—— C++11列表初始化(统一了初始化方式)

C++11新特性:19—— C++11列表初始化(统一了初始化方式)

c++11 统一初始化

c++11 统一初始化

第6课 列表初始化_统一初始化

[C++11] --- 易用性改进