第三章:对象与基本类型(四)

类型别名

我们可以为类型引入别名,从而引入特殊的含义或者便于使用,比如size_t。通常来说,引入类型别名有两种方式

  • typedef
    typedef int MyInt;
    
  • using(从C++11开始)
    using MyInt = int;
    

使用using要比typedef更加优化易读,比如

	typedef char MyCharArr[4];	// 读起来比较混乱
	using MyCharArr = char[4];	// 读起来清晰明了

我们需要区分类型别名与指针、引用之间的关系

  • 应该将指针的类型别名认为视为一个整体,在此基础上如果引入了常量则代表常量指针而不是指向常量的指针,比如
    using IntPtr = int *;
    int x = 3;
    const IntPtr ptr = &x;	// const修饰整个Int *
    int y = 4;
    ptr = &y;				// 这里会报编译错误
    

    注意这里的const IntPtr ptr本质上的类型为int * const而不是const int *

  • 不能通过类型别名构造引用的引用,比如
    using RefInt = int &;
    using RefRefInt = RefInt&;			// 这里的类型同样为int &
    

类型的自动推导

从C++11开始,我们可以通过初始化表达式自动推导对象的类型,比如

auto x = 3.5 + 15l;

但是,我们需要明白自动推导类型并不意味着弱化类型,我们推导出来的对象还是强类型,从类型推导出来之后类型就确定了,后续不可以更改类型

自动推导有几种常见的形式:

  • auto:最常见的形式,但是可能会产生类型退化,比如

    int x1 = 3;
    int & ref = x1;
    auto ref2 = ref;				// 这里的int&退化成了int
    
  • const auto/constexpr auto:推导出的是常量/常量表达式类型

  • auto &:推导出引用类型,同时避免了类型退化,比如

    int x[3] = {1,2,3};
    auto x1 = x;			// 类型为int*
    auto & x2 = x;			// 类型为 int(&)[3]
    
  • decltype(exp):返回exp对应的表达式的类型,但是不会产生退化,比如

    decltype(3.5+15l) x = 3.5+15l;
    

    但是需要注意,如果其中的exp是左值的话,decltype会自动加一个引用类型,比如

    int x = 3;
    int * ptr = &x;
    decltype(*ptr)// 这里的类型为int &
    

    同时还需要注意,如果exp是一个变量名称,那么decltype只会推导出变量的类型,不会添加引用,比如

    int x = 3;
    decltype(x)				// 这里的类型为int 
    

    如果想要让他加引用的话我们可以对在变量名称外加一个(),比如

    int x = 3;
    decltype((x))			// 这里的类型为int & 	
    
  • decltype(auto):从C++14开始引入,简化了decltype的使用,比如

    decltype(3.5+15l) x = 3.5+15l;
    

    可以被简化为

    decltype(auto) x = 3.5+15l;
    

    这样做既避免auto引入的类型退化,也避免了decltype必须要重复书写表达式的问题

  • concept auto:从C++20开始支持,表示了一系列的类型,对auto的自动类型推导引入了类型限制,比如

    std::integral auto x = 3;		//类型为int
    std::integral auto x = 3.5;		//报错,因为3.5不属于整型这个concept
    

域(scope)表示了程序中的一部分,其中的名称有唯一的意义,比如

void fun(){
int x = 3
}
int main(){
int x = 3;
}

其中的两个x属于不同的域,所以不会发生重复定义的问题。

域分为很多中,典型的比如:

  • 全局域(global scope):程序最外围的域,其中定义的是全局对象
  • 块域(block scope):使用{}所限定的域,其中定义的是局部对象
  • 类域、命名空间域等等

域可以进行嵌套,嵌套域中的名称会隐藏,比如

{
int x = 3;
	{
	int x = 5;
	std::cout << x << std::endl;		//这里输出的一定是5
	}
}

对象的生命周期

对象的生命周期起始于被初始化的时刻,终止于被销毁的时刻,结合域来说的话就是

  • 全局对象的生命周期是整个程序的运行期间(广义的概念,不同的全局对象的生命周期根据初始化的顺序有所不同)
  • 局部对象的生命周期起始于被初始化的时刻,终止于所在域被执行完成后,比如
    {
    int x = 3;
    	{
    	std::cout << x << std::endl;		//这里输出的一定是3
    	int x = 5;
    	}
    }
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值