读书笔记2.2

处理类型

类型别名

  含有关键字typedef 的声明语句定义的不再是变量而是类型别名。且这里的声明和其它声明一样,可以包含类型修饰,即也可以由基本数据类型构造出复合类型来。
  新标准增加了使用别名声明来定义类型的别名。
  语法为:using 别名(新名字) = 已有类型名。如:
using SI = Sales_item; //SI是Sales_item的同义词或者代名词
  类型别名和类型的名字等价,只要是类型的名字出现的地方,就可以使用类型别名。
指针、常量和类型别名
  如果类型别名指代的是复合类型或常量,则需要将复合类型看成基本类型。

示例代码:
typedef char *pstring;
const pstring cstr = 0;
            //正确的理解: const (char*)cstr = 0;     即:cstr是指向char型变量的常指针
            //错误的理解: const char* cstr = 0;      即:cstr是指向const char型变量的指针
const pstring *ps;
            //正确的理解: const (char*)*ps;          即:ps是二重指针,其指向的是一个常指针
            //错误的理解: const char*    *ps;            即:ps是二重指针,其指向的是一个指向常量的指针

auto类型说明符

  auto让编译器通过初始值来判断变量的类型。显然,auto变量是必须有初始值的。当用auto在一条语句中声明多个变量时,各个变量给定的初始值类型必须一致。

复合类型、常量和auto
  编译器推断出来的auto类型有时候和初始值的类型并不完全一致,编译器会适当的改变结果类型使其更符合初始化规则。
  1、使用引用时,尤其是引用被用作初始值时,编译器会以引用对象的类型作为auto的类型。
  2、auto一般会忽略掉顶层c会被保留下来。onst,同时底层const
  

//示例代码片段
const int ci = i , &cr = ci ;
auto b = ci ;   //b是一个int型(ci的顶层const特性被忽略)
auto c = cr ;   //b是一个const int型(所有用于声明引用的const都是底层const,将保留,但ci本身的顶层const特性被忽略)
auto d = &i ;   //d是一个指向int型的指针
auto e = &ci;   //e是一个指向const int型的指针(对常量对象取地址是一种底层const)

  3、若需要推断出的auto类型是一个顶层const,需要明确指出:

//示例代码片段
const auto f = ci ;     //ci推出是int型,f是const int 型

  4、可以将引用类型设为auto,此时原来的初始化规则依旧适用:

//示例代码片段
auto &g = ci ;      //ci是一个const int型,g是一个int型常量的引用
auto &h = 42 ;      //错误,不能将非常量的引用绑定于字面值
const auto &j = 42 ;//正确,常量的引用可以绑定于字面值

  5、设置一个类型为auto的引用时,初始值中的顶层const属性仍保留。(注意:在一条语句中定义多个变量,符号&和*只从属于某个声明符,而非基本数据类型的一部分。)

//示例代码片段
auto k = ci , &l = i;       //得到k是int型,l是int的引用
auto &m = ci , *p = &ci;    //得到m是const int型的引用,p是const int的指针
auto &n = i , *p2 = &ci ;   //错误,i是int型,而ci是const int

decltype类型指示符

decltype:选择并返回(表达式所得到的)操作数的类型。在此过程中编译器只分析表达式的类型,却不实际计算表达式的值。

decltype (f()) sum = x;     //sum的类型就是函数f的返回类型

1、decltype处理顶层const和引用的方式与auto不同,它会将返回值的类型全部录入包括顶层const和引用在内。

const int ci = 0 , &cj = ci ;
decltype (ci) x = 0;    //x为const int型
decltype (cj) y = x;    //y为const int& 绑定到x上
decltype (cj) z;        //错误,z是const int&必须初始化

**注意:引号从来只是对应对象的代名词出现,只有在decltype处例外
1、decltype的结果可以是引用类型,但表达式的结果要能够作赋值语句的左值

int i = 42*p = &i , &r = i ;
decltype (r+0) b ;  //正确,加法的结果是int型,故b为(未初始化的)int型(r是引用类型,decltype (r)必是引用类型。为了让表达式是r所绑定对象的类型,必须让r成为表达式的一部分,所以这里使用了decltype (r+0)。)
decltype (*p) c ;   //错误,c是int&型,必须初始化

2、如果表达式的内容是一个解指针引用操作,则decltype将得到引用类型。如:decltype (*p) 得到的是int&型,而非int型。
3、decltype和auto的一个重要区别是,decltype的结果类型和表达式形式密切相关:如果decltype使用的是不加括号的变量则得到的结果是该变量的类型;若给变量加上括号,编译器会将其变成一个表达式,使用decltype就会得到一个引用类型。

//decltype的表达式如果使用加括号的变量,结果将是引用
decltype (i) e; //正确,e是一个未经初始化的int型
decltype  ((i)) d;  //错误,d是int&型必须初始化

4、赋值是产生引用的一类典型表达式,引用的类型就是左值的类型。也就是说,如果i是int型,则表达式i = x的类型是int&型。**

自定义数据结构

1、定义Sales_datda类
以关键字struct开始,紧跟着类名、类体和类结束的分号。类体部分由一对花括号包围形成一个新的作用域;分号必不可少。如:

struct Sales_datda{
    std::string booksNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

2、类的数据成员的初始化:其初始化和之前介绍的初始化类似,或者放在花括号里,或者放在等号右边,但不能使用圆括号。
3、为了确保各个文件中类的定义一致,类通常呗定义在头文件中,而且类所在的头文件的名字应该与类名一致。头文件一旦反生改变,相关的源文件都必须重新编译以获得更新过的声明。

预处理概述

确保头文件多次包含仍能安全工作的常用技术是:预处理器。

#define     //把一个名字设定为预处理变量
#ifdef      //当且仅当变量已经定义时为真
#ifndef     //当且仅当变量未定义时为真
一旦检查结果为真则执行后续操作,直到遇到 #endif 为止
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值