C++ 各种对象的初始化、默认初始化情况


前言

C++的各种类型的初始化主要在默认初始化以及初始化格式上有区别。初始化是指一个对象在创建时获得了一个特定的值。

一、初始化格式

1.算术类型的初始化

	//	所有的算术类型都可以采用以下四种方式进行初始化
	int a_int = 1;	
	int a_int = { 1 };
	int a_int(1);
	int a_int{ 1 };

	//	通过花括号初始化的形式被称为列表初始化,以此方式初始化时若初始值存在丢失信息的风险,编译器将报错。
	int a_int{ 1.5 };	//	错误:1.5会被丢失小数信息
	int a_int{ 10000000000000000000 };	//	错误:初始化的值过大超出int类型容量

	unsigned int a_uint{ -1 };	//	错误:使用负值初始化无符号数

	long b_int{ 1 };	//	正确
	long b_int{ 1.6 };	//	错误:依然是1.6会被丢失小数信息

	double c_double{ 1.8 };	//	正确
	bool d_bool{ 6 };	//	错误:bool类型实际值只有0和1

	char e_char{ '3' };	//	正确

2.复合类型的初始化

2.1 引用的初始化

定义引用时,程序把引用和初始值绑定在一起。引用并非一个对象,只是为绑定对象起的另一个名字。

	int i = 42;
	int& a = i;	//	正确:通过修改a修改i的值
	int& b;	//	错误:引用将和它的初始值一直绑定在一起,因此引用必须初始化
	double& c = i;	//	错误:引用的类型需要与绑定对象一致

2.2 指针的初始化

指针相对于引用来说,也实现了对其他对象的间接访问。不同点在于,其一,指针本身是一个对象,可以赋值和拷贝,也可以在生命周期中先后指向几个不同的对象。其二,指针无须在定义时赋初值。
指针在初始化时经常要结合取地址符(操作符&)以及解引用符(操作符*)。因为指针的值是一个对象的地址,通过取地址符对目标对象取地址给指针进行赋值。当需要使用指针所指对象的值时,可以通过解引用符来进行获取。

	int i = 42;
	int* p = &i;	//	正确:p的值为i的地址
	cout << p << endl;	//	输出的是i的地址
	cout << *p << endl;	//	*p输出的是i的值

	double* q = &i;	//	错误:指针初始化中,其类型必须与目标对象相同。

	int* p1 = nullptr	//	正确:指针初始化为空指针

2.3 数组的初始化

数组由数组名字以及其维度组成,维度必须大于0,编译的时候维度应该是已知的,也就是说维度必须是一个常量表达式。

	//	维度必须是常量
	int arr[10];	//	正确:直接进行初始化,但是其中的值是无法预测的
	int a = 42;		
	const int b = 42;
	int arr_1[a];	//	错误:维度必须是常量
	int arr_2[b];	//	正确:b是一个常量
	int arr_3[get_size()];	//	当get_size()为一个常量表达式时正确

	//	数组中的元素进行默认初始化
	int b[3] = { 0,1,2 };	
	int b_1[] = { 0,1,2 };	//	维度自动定义为3
	int b_2[5] = { 0,1,2 };	//	此时数组中的值为0,1,2,0,0

	//	字符串常量在其末尾处有一个空字符
	char a1[] = { 'a','b','c' };	//值为'a','b','c'
	char a2[] = "abc";	//值为'a','b','c','\0'
	string temp = "abc";
	const char *a3 = temp.c_str();	//	C++的字符串string赋值给char数组
	const char *a3 = { temp.c_str() };	//	同上效果
	char n[20];
	string s = "hello,world!";
	strcpy(n, s.c_str());	//	正确,但是不安全显示过时,需加入对应包以及解除警告,#include <cstring>以及#pragma warning (disable:4996) 

	//	数组不能拷贝赋值
	int c[] = { 0,1,2 };	
	int c1[] = a;	//	错误:数组不能拷贝赋值
	c1 = c;		//	错误:数组不能拷贝赋值
	
	//	复杂的数组声明
	int x[10];
	int* d[10];		//	正确:含10个整数指针的数组
	int& d1[10] = x;	//	错误:无法定义引用的数组,引用不是对象
	int(*d2)[10] = &x;	//	正确:d2是一个指针,指向一个含10个整数的数组
	int(&d3)[10] = x;	//	正确:d3是一个引用,引用一个含10个整数的数组

3 标准库类型string的初始化

	string s1;	//	初始化值为空字符串
	string s2(s1);	//	拷贝
	string s3("value");	//	初始化为字面值"value",不含最后的空字符
	string s5 = "value";	//	同上
	int n = 9;
	string s4(n, 'c');	//	初始化为n个'c'连着的

4 标准库类型vector的初始化

	vector<int> v1;	//	默认初始化,其中不含任何元素
	vector<int> v2(v1);	//	用v1拷贝给v2
	vector<int> v3 = v1;	//	用v3拷贝给v1
	
	//	以下四种初始化方式,n未声明则为整数,当n可以表示列表的初始值,也可以表示元素的数量,一般情况下可以用花括号或圆括号进行区分。
	vector<int> v4(n);	//	有n个元素,每个元素都是一个T
	vector<string> v4(n);	//	n="w",n的值不是整数时,默认切换为花括号的形式,有一个元素,为n
	vector<int> v4{n};	//	只有1个元素,值为T的初始值
	vector<int> v4(n, val);	//	有n个元素,每个都为val
	vector<string> v4(n, val);	//	n="2",当n的值不是整数时,默认切换为花括号的形式,有两个元素,分别为n和val
	vector<int> v4{n, val};	//	有两个元素,分别是n或val

	vector<int> v6 = { a,b,c };	//	列表的初始化形式

二、默认初始化

默认初始化主要区别在于是否在函数体内部,一般在函数体外会进行默认初始化,函数体内大多不会进行初始化。

	int a;		//	初始化为0
	float b;	//	0
	double c;	//	0
	bool d;		//	0
	char e;		//	''
	//	string类型不管在函数体外还是体内都进行默认初始化
	string f;	//	空字符串""
	int g[3];	//	g中元素全初始化为0
	//	vector不管在函数体外还是体内都进行默认初始化
	vector<int> h(10);		//	h中元素全初始化为0
	vector<string> i(10);	//	i中元素全初始化为空字符串""
	//	自定义数据结构也是在函数体外进行默认初始化,函数体外不会进行初始化
	struct mine {
		int b;
	};
	mine j;		//	j中成员b有初始值0
	int main()
	{
		int a1;		//	无初始值
		float b1;	//	无
		double c1;	//	无
		bool d1;	//	无
		char e1;	//	无
		string f1;	//	空字符串""
		int g1[3];	//	数组内元素都是一些无法预测的值
		vector<int> h1(10);	//	其中元素全为0
		vector<string> i1(10);	//	其中元素全为空字符串""
		mine j1;	//	j1中成员b中无初始值
	}

当使用没有初始值的对象时将发生错误。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值