第一章:变量和基本数据类型

基本数据类型

数据类型是程序的基础,它告诉我们数据的意义以及能进行的操作。

c++定义了一套包括算术类型 ( arithmetic type) 和空类型( void )的内置类型

基本内置类型

算术类型

算术类型的尺寸在不同的机器上可能不相同,下图是c++标准规定的最小尺寸。

类型 含义 最小尺寸
bool 布尔类型 未定义
char 字符 8位
wchar_t 宽字符 16位
char16_t Unicode 字符 16位
char32_t unicode 字符 32位
short 短整型 16位
int 整型 16位
long 长整型 32位
long long 长整型 64位
float 单精度浮点数 6位有效数字
double 双精度浮点数 10位有效数字
long double 扩展精度浮点数 10位有效数字

带符号类型和无符号类型

在c++中整型分为带符号和无符号,带符号的可以表示正数、负数。不带符号的仅能表示正数。

int   a = 1;//默认有符号
unsigned int b = 12; //无符号
signed  int c = -1; //有符号

类型转换

对象的类型定义了对象能包含的数据和能参与的运算,其中一种运算被大多数类型支持,就是将对象从一种给定的类型转换为另一种相关类型。

bool b  = 42; b为true,仅初始值为0时b=false

int i = b; // i的值为 1 

double pi  = i;

有一点需要注意,不要混用带符号类型不带符号类型,否则为产生意想不到的结果。

字面值常量

一个形如42的值值被称作字面值常量,这样的值一望而知,每个字面值常量都对应一种数据类型。


变量

变量提供一个具名的、可供程序操作的存储空间,c++中每一个变量都有其数据类型,数据类型决定着变量所占内存空间的大小和布局方式、该空间能存储的值的范围,以及能参与的运算。对c++程序员来变“变量”和“对象”一般可以交互使用。

变量的定义

变量定义的基本形式是:首先是类型说明符,随后紧跟由一个或多个变量组成的列表

int  sum  = 0value , units_sold =0;都是int,初值为0

多种初始化方式
int  a  =0;
int  a ={0}; c++11新标准的一部分,被称为列表初始化
int a{0};
int a(0);

默认初始化
int  a ; //值为0,如果定义在函数内将不被初始化,其值为未定义,如果使用来引发错误

变量声明和定义的关系

为了允许把程序拆分成多个逻辑部分来编写,c++语言支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译。

extern int i ; 声明而非定义 i
int j ;声明并定义j
extern int k =3; 定义

标识符

c++的标识符(identifier)由字母、数字和下画线组成,其中必须以字母或下画线开头,标识符的长度没有限制,但是对大小写字母敏感。

名字的作用域

不论是在程序的什么位置,使用到的每个名字都会指向一个特定的实体:变量、函数、类型等。然而,同一个名字如果出现在程序的不同位置,也可能指向的是不同实体。

{
这是一个作用域,以花括号分隔
}

复合类型

复合类型(compound type)是指基于其它类型定义的类型。c++语言有几复合类型特别重要。

引用

引用(reference)为对象起了另外一个名字,引用类型引用另外一种类型。

int iVal = 1024;

int &refVal = iVal; refVal指向ival(是iVal的另一个名字);

int &refVal2;  报错,引用必须被初化。无法将引用重新绑定到另外一个对象上,所有必须初始化

int &refVal3 = 31; 报错,引用类型的初始值必须是一个对象

引用并非对象,相反的,它只是为一个已经存在的对象所起的另外一个名字

指针

指针是指向另外一种类型的复合类型。指针本身是一个对象。而引用不是对象。

int *ip1 ;ip1指向int类型对象的指针

int  i  =5;

double *ip2 = &i; ip2是指向变量i的指针,&是取地址符

cout<< *ip2<<endl; 打印 出5*是解引用符

*ip2 = 3; i被改为3

cout<<ip2<<endl; 打印指针对象
指针值

指针的值(即地址)应属下列4种状态之一

  1. 指向一个对象
  2. 指向紧邻对象所占空间的下一个位置
  3. 空指针,意味着指针没有指向任何对象
  4. 无效指针,也就是上述情况之外的其它值

空指针

等价定义,都是空指针
int  *ip =nullptr;c++11新标准加入。一种特殊类型字面值
int *ip =NULL; 需要#include cstdlib ,NULL是预处理变量,它的值为0
int *ip =0;


if(ip){
ip的值为0,因此条件为false,任何非空指针都为true
}



const限定符

const的引用

有时我们希望定义这样一种变量,它的值不能被改变,可以用关键字const对变量的类型加以限定。

const int  buf =1024; 是个常量

buf =3;错误   


const int ci =1024;
const int &r1 = ci;正确,都是常量
r1 = 33;错误
int &r2 =ci;错误,试图让一个非常量引用指向一个常量对象。反过来是允许的

指针和const

与引用一样,也可以令指针指向常量或非常量,类似于常量引用,指向常量的指针,不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针。

const double pi =3.14;
double *d =&pi;错误
const  double *id1 =&pi;正确

double dVal = 3.0;
*id1 = &dVal; 正确

const 指针
指针是对象而引用不是,因此就像其它对象类型一样,允许把指针本身定为常量。常量指针(const pointer) 必须初始化。而且一亘初始化完成,则它的值(存放在指针中的那个地址)就不能改变了。

int errNum =0;
int *const curErr = &errNumb; curErr将一直指向errNumb。(指针本身是一个常量)
const double pi =3.14;

指针本身是一个常量,并且指向一个常量指针
const double *const pip =&pi;//pip是一个指向常量对象的常量指针。


//常量指针仅公本身是常量,还是可以改变其指向的对象的值
if(*curErr){
*curErr  = 0;
}

顶层const

指针本身是一个对象,它又可以指向另外一个对象,因此,指针本身是不是常量以及指针所指的是不是一个常量就是两个相互独立的问题,用名词顶层const(top-level const)表示指针本身是一个常量,而且名词底层const(low-level const)表示指针所指的对象是一个常量。

比较特殊的是,指针类型既可以是顶层const也可以是底层const,这一点和其它类型区别明显

int i =0;
int *const p1 =&i; 不能改变p1,顶层const
const int ci =42; 不能改变ci,顶层const 
const int *p2 = &ci;允许改变p2的值,底层const
const int *const p3 =p2;靠右的const 是顶层const ,靠左的是底层const



当执行对象的拷贝操作时,常量是顶层const还是底层const区别明显,拷入和挂出的对象必须具有相同的底层const 资格。一般来说,非常量可以转换成常量,反之则不行。

int *p =p3; 错误p3包含底层const定义,p没有


constexpr和常量表达式

常量表达式(const expression)是指值不会改变并且在编译过程就能得到计算结果的表达式,显然,字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式,

const int max=20;常量表达式
const int max2 = max+1;常量表达式
int max3 = 24;不是

consterpx常量
在一个复杂系统中,很难分辨一个初始值到底是不是常量表达式。

constexpr int  mf =20; 常量表达式
constexpr int mf2 =mf+1;常量表达式
consterpr int mf3 =size() ;只有当size是一个consterpr函数时才是一条正确的声明语句。

指针和consterpx
必须明确一点,在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的无关

const int *p =nullptr;p是一个指向整形常量的指针
constexpr int *q = nullptr;q是一个指向整数的常量指针

处理类型

类型别名

typedef double wages;  wages是double的同义词
typedef wages base *p;  basedouble的同义词,p是double*同义词

新标准新写法
using wages = double;

auto类型说明符

新标准auto类型说明符,用于类型推断

auto i =0,*p=&i;

decltype

decltype(f()) sum = x; sum的类型就是函数f的返回类型(并不会实际调用f函数)



const int ci =0;&cj =ci;
decltype(ci) x =0; x的类型是const int 
decltype(cj) y =x; y的类型是const int&,y绑定到变量x
decltype(cj)z;  错误,z是一引用,必须初始化

引用从来都作为其所指对象的同义词出现,只有用在decltype处是一个例外

decltype 和引用

int i =42,*p=&i;&r=i;
decltype(r+0)b;  正确,加法的结果是int 
decltype(*p) c;错误 c是int&,必须初始化
decltype((i)) d;错误,d是int&,必须初始化
decltype(i) e;正确,e是一个未初始化的int

decltype((variable))的结果永远是引用,而 decltype(variable)本身是一个引用时才是引用。

猜你喜欢

转载自blog.csdn.net/chinaaaaaaaaaaa/article/details/80758443