类型别名声明、auto类型指示符、decltype类型指示符

版权声明:版权归作者所有,转发请标明 https://blog.csdn.net/weixin_40087851/article/details/82755258

类型别名声明

  • 类型别名是一个名字,它是某种类型的同义词。

    • 使用类型别名的用处:让复杂的类型名字变得简单明了、易于理解和使用,还有助于程序员清楚地知道使用该类型的真实目的。
  • 有两种方法可用于定义类型别名。(1)关键字typedef;(2)别名声明using。

  • 关键字typedef:含有typedef的声明语句定义的不再是变量而是类型别名。

    • (注意!!!)typedef是有作用域的。例如typedef double DOU;在size()函数中有效,但在main()函数中无效。
#include<iostream>

using namespace std;
typedef double DOUBLE;

void size() {
	typedef double DOU;
	DOU d = 12.121212;
	cout << d << endl;
}

int main(int argc, char* argv[]) {
	DOUBLE d = 12.121212;
	cout << d << endl;
	//DOU d = 12.121212;   //错误:未定义标识符"DOU"
	getchar();
	return 0;
}
  • 别名声明(using 声明)来定义类型别名:

    • (注意!!!)using声明是有作用域的。例如using DOU = double;在size()函数中有效,但在main()函数中无效。
#include<iostream>

using namespace std;
using DOUBLE = double;

void size() {
	using DOU = double;
	DOU d = 12.121212;
	cout << d << endl;
}

int main(int argc, char* argv[]) {
	DOUBLE d = 12.121212;
	cout << d << endl;
	//DOU d = 12.121212;   //错误:未定义标识符"DOU"
	size();
	getchar();
	return 0;
}

auto类型说明符

  • 编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚地知道表达式的类型。但在实际应用中,能够清楚地获知表达式的类型并不容易。为了解决这个问题,C++11新标准引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。

  • auto让编译器通过初始值来推算变量的类型。显然,auto定义的变量必须有初始值

#include<iostream>

using namespace std;

int main(int argc, char* argv[]) {
	//auto i;  //无法推导"auto"类型(需要初始值设定项)
	int a1 = 10;
	double a2 = 10.5;
	auto res = a1 + a2;  //res的类型为double
	cout << res << endl; //20.5
	getchar();
	return 0;
}
  • 复合类型、常量和auto:编译器推断出来的auto类型有时候和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则。

  • 首先,使用引用其实就是使用引用的对象,特别是当引用被用作初始值时,真正参与初始化的其实是引用对象的值。此时编译器以引用对象的类型作为auto的类型

#include<iostream>

using namespace std;

int main(int argc, char* argv[]) {
	int i = 0, &r = i;
	auto a = r;  //a的类型为int
	getchar();
	return 0;
}
  • 其次,auto一般会省略顶层const,同时底层const则会保留下来,比如当初始值是一个指向常量的指针时:

    • (注意!!!)语句auto e = &ci;中, e是一个指向整数常量的指针(对常量对象取地址是一种底层const)
#include<iostream>

using namespace std;

int main(int argc, char* argv[]) {
	int i = 0, &r = i;
	const int ci = i, &cr = ci;
	auto b = ci;  //b是一个整数(ci的顶层const特性被忽略了)
	auto c = cr;  //c是一个整数(cr是ci的别名,ci本身是一个顶层const,顶层const特性被忽略了)
	auto d = &i;  //d是一个整型指针(整数的地址就是指向整数的指针)
	auto e = &ci; //e是一个指向整数常量的指针(对常量对象取地址是一种底层const)
	getchar();
	return 0;
}
  • 如果希望推出来的类型是一个顶层const,需要明确指出:
const int ci = 10;
const auto f = ci; //ci的推演类型是int,f是const int

decltype类型指示符

  • 有时候,希望从表达式的类型推断出要定义的变量的类型,但是不想用该表达式的值初始化变量。

  • C++11新标准引入了第二种类型说明符decltype,作用:选择并返回操作数的数据类型

    扫描二维码关注公众号,回复: 3887730 查看本文章
  • decltype处理顶层const和引用的方式与auto有些许不同。

  • 如果decltype使用的表达式是一个变量,则decltype返回该变量的类型。

#include<iostream>

using namespace std;

int main(int argc, char* argv[]) {
	int i = 0, &r = i;
	const int ci = i, &cr = ci;
	decltype(ci) x = 0;  //x的类型是const int 
	decltype(cr) y = x;  //y的类型是const int& 
	//decltype(cr) z;  //错误:z是一个引用,必须初始化
	getchar();
	return 0;
}
  • 如果decltype使用的表达式不是一个变量,则decltype返回表达式结果对应的类型。

  • 如果表达式的内容是解引用操作,则decltype将得到引用类型。正如我们所熟悉的,解引用指针可以得到指针所指的对象,而且还能给这个对象赋值。因此,decltype(*p)的结果类型是int&,而非int。

#include<iostream>

using namespace std;

int main(int argc, char* argv[]) {
	int i = 42, *p = &i, &r = i;
	decltype(r + 0) b;  //正确:加法的结果是int,因此b是一个(未初始化的)int
	//decltype(*p) c;     //错误:c是int&,必须初始化
	getchar();
	return 0;
}
  • 切记:decltype((variable))(注意是双层括号)的结果永远是引用,而decltype(variable)结果只有当variable本身就是一个引用时才是引用。
#include<iostream>

using namespace std;

int main(int argc, char* argv[]) {
	int i = 10;
	//decltype((i)) d;  //错误:d是int&,必须初始化
	decltype(i) e;     //正确:e是一个(未初始化的)int
	getchar();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40087851/article/details/82755258
今日推荐