C++11——初始化列表,变量类型推到,默认成员函数控制

Posted 两片空白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++11——初始化列表,变量类型推到,默认成员函数控制相关的知识,希望对你有一定的参考价值。

目录

一.初始化列表

        1.1 C++98的初始化

        1.2 C++11的初始化

        1.3 自定义类型的初始化

二.变量类型推导

        2.1 为什么需要变量类型推导

        2.2 decltype类型推导

 三.默认成员函数控制

        3.1 显示缺省函数

        3.2 删除默认函数


一.初始化列表

        1.1 C++98的初始化

        在C++98中,数组可以用"{}"整体初始化。

比如:

int arr[] = {1,2,3,4,5,6};

但是对于自定义类型却不能用"{}"进行初始化。

比如:

vector<int> v = {1,2,3,4,5,6};//编译错误

使得我们必须先将自定义类型定义出来,再将每一个成员变量插入进去。导致很不方便

        1.2 C++11的初始化

         针对上面这种情况,C++11增加了可以使用"{}"来初始化自定义类型的功能。使得内置类型和自定义类型都可以使用"{}"来进行初始化。

int main(){

	//内置类型
	int a{ 10 };
	int b = { 10 };
	int c{ 1 + 2 };

	//自定义类型
	vector<int> vv1{ 1, 2, 3, 4, 5, 6 };
	vector<int> vv2 = { 1, 2, 3, 4, 5, 6 };

	list<int> l1{ 1, 2, 3, 4, 5, 6 };
	list<int> l2 = { 1, 2, 3, 4, 5, 6 };

	map<string, string> dict{ { "left", "左" }, { "right", "右" }, { "up", "上" } };

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

	system("pause");
	return 0;
}

注意:C++11是再C++98基础上进行升级,C++98的用法还可以使用。

        初始化列表可以再"{}"前使用等号,效果和不使用等号相同。

        1.3 自定义类型的初始化

  • 自定义类型具体数量的列表初始化

        当我们自定义的类型的成员变量是一个具体数字时,我们直接调用列表初始化

class Test{

private:
	int _x;
	int _y;
	int _z;
public:
	Test(int x = 0, int y = 0, int z = 0)
		:_x(x)
		, _y(y)
		, _z(z)
	{}
};


int main(){
    //调用构造函数
	Test t0(4, 5, 6);
	Test t1{ 1, 2 };
	Test t2{ 1, 2, 3 };

	//Test t3{ 1, 2, 3, 4 };//编译错误,不能大于Test成员变量数

	system("pause");
	return 0;
}

 但是列表里的值不能大于Test成员变量数,否则会编译错误。

错误信息为:

  •  当自定义类型的成员变量是动态的,可以取多个值时

        想要支持可以在初始化时列表输入多个值,需要在类中重载一个带有initializer_list类型参数的构造函数。

class String{

private:
	char *_str;//大小是动态的
	int _capacity;
	int _size;
public:
	//这样就可以使用{}进行初始化
	String(initializer_list<char> str)
		:_capacity(str.size())
		, _size(0)
	{
		_str = new char[_capacity];
		for (auto ch : str){
			_str[_size++] = ch;
		}
	}


	String(char *str = nullptr, int cap = 0, int size = 0)
		:_str(str)
		, _capacity(cap)
		, _size(size)
	{}
};


int main(){

	String sh{ 'a', 'b', 'c', 'd','\\0' };
	
	return 0;
}

 initializer_list作用:

  •  initializer_list是一个轻量级容器类型
  • 可以接受任意长度的初始化列表,但是元素必须是要相同的或者可以转换为T类型的。
  • 只有三个成员接口,begin(),end(),size(),其中size()返回initialzer-list的长度。
  • 只能被整体的初始化和赋值,遍历只能通过begin和end迭代器来,遍历取得的数据是可读的,是不能对单个进行修改的。

此外initialzer-list<T>保存的是T类型的引用,并不对T类型的数据进行拷贝,因此需要注意变量的生存期。比如我们不能这样使用:

std::initializer_list<int> func(void)
{
    auto a = 2, b = 3;
    return{ a, b };
}

虽然看起来没有任何问题,且能正常编译通过,但是a,b是在func内定义的局部变量,但程序离开func时变量a,b就销毁了,initialzer-list却保存的是变量的引用,因此返回的将是非法未知的内容。

二.变量类型推导

        2.1 为什么需要变量类型推导

        在定义变量时,我们必须给出变量的类型,编译器猜允许定义。但是当我们不知道需要的实际类型该怎么给,或者类型写起来很复杂时。不方便程序员编写。

比如:

int main(){

	char a = 125;
	char b = 125;
	//超出char最大范围,写成char接收造成数据丢失。如果让编译器来推导出实际类型,不会存在数据丢失
	char c = a + b;
	
	std::map<std::string, std::string> dict{ { "left", "左" }, { "right", "右" }, { "up", "上" } };
    //写起来很麻烦
	std::map<std::string, std::string>::iterator it = dict.begin();
	while (it != dict.end()){
		std::cout << it->first << ":" << it->second << std::endl;
		it++;
	}

	
	return 0;
}

 在C++11中可以使用auto来进行类型推导,使得程序的书写更加方便。比如:

 但是auto的使用也右一些不足,使用auto的对象必须先进行初始化,否则编译器无法推导出auto的实际类型。并且auto不能推导函数返回值类型和函数参数类型。

        在表达式运行完之后进行类型推导,运行完才知道结果的实际类型,为运行时类型识别(RTTI:Run-Time Type Identification)。

 在C++98中已经支持RTTI:

  • typeid只能查看类型,不能用结果类型定义对象
  • dynamic_cast只能应用于含有虚函数的继承体系中。

运行时类型识别的缺陷是降低程序运行效率。

        2.2 decltype类型推导

        decltype是根据表达式和函数返回推演出实际类型,可以用来定义变量。

  • 推演表达式的类型作为变量的定义类型

  • 推演出函数返回值的类型

 三.默认成员函数控制

        3.1 显示缺省函数

        一个类会默认生成6大成员函数,构造函数,拷贝构造函数,析构函数,取地址函数,const取地址函数。当我们显示定义时,编译器就不会生成对应的函数。

        有一种情况:当我们显示出带参数不带缺省的构造函数时,编译器不会默认生成构造函数,当我们需要实例化无参对象时,会因为没有的构造函数而报错。

        在C++11中,我们可以在默认函数定义或者生命时加上=default,从而显示的指示编译器生成该函数的默认版本。用=default修饰的函数称为显示缺省函数。

        3.2 删除默认函数

        在C++98中,如果想限制外部使用默认函数,可以将函数设置成私有private,并不给定义。在外部调用时,就会报错。

        在C++11中,在默认函数后面加上=delete,编译器就不会生成对应的默认函数。称=delete修饰的函数为删除函数。

 注意:避免删除函数和explicit一起使用

 

以上是关于C++11——初始化列表,变量类型推到,默认成员函数控制的主要内容,如果未能解决你的问题,请参考以下文章

C++11的新鲜事儿~

C++ 11特性

C++11常用语法-壹

C++ 11特性

C++11特性(详细版)

C++11特性(详细版)