C++ primer第2章

从书上抄的

第二章

2.1 基本内置类型

2.2变量

变量提供一个具名的、可供程序操作的存储空间。C++中的每个变量都有其数据类型,数据类型决定着变量所占空间的大小和布局方式、该空间能存储的值的范围,以及变量能参与的运算。

2.2.1变量定义

初始化

初始化和赋值是完全不同的操作。初始化是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来替代。

列表初始化

c++11,用花括号来初始化变量。

赋值,允许信息丢失。初始化,不允许信息丢失,编译器会报错。

 2.2.2变量声明和定义的关系

c++支持分离式编译,即允许将程序分割为若干个文件,每个文件可被独立编译。

如果将程序分为多个文件,则需要有在文件间共享代码的方法。

声明,使得名字为程序所知。定义,负责创建与名字关联的实体。

extern 表示声明外部,给更多地方使用。(支持分离式编译)

若static extern,表示仅在本文件使用

extern 不是定义,而是引入(声明)在其他源文件中定义的非static全局变量。

c++是静态类型语言,在编译阶段检查类型。

编译器负责检查数据类型是否支持要执行的运算,如果试图执行类型不支持的运算,编译器将报错,且不生成可执行文件。

2.3符合类型

复合类型是基于其他类型定义的类型。(主要有:引用和指针)

数据类型 变量名列表;

2.3.1 引用

引用不是对象,只是别名。

2.3.2 指针

与引用类似,指针也实现了对其他对象的间接访问。

赋值和指针

指针和引用都能提供对其他对象的间接访问。区别是:引用不是对象。一旦定义了引用,就无法令其再绑定到另外的对象。

指针和它存放的地址可以修改。可以令它存放新的地址,从而指向一个新的对象。

2.3.3 理解复合类型

变量的定义包括:一个基本数据类型和一组声明符。一条定义语句,虽然基本数据类型只有一个,但是声明符的形式却可以不同。

int i=1024, *p=&i, &r=i;//

指向指针的指针 

指向指针的引用

int i = 42;

int *p;  //p是一个int型指针

int *&r = p;  //r是一个对指针p的引用

r=&i;  //r引用了一个指针,给r赋值&i就是令p指向i

*r=0;  //解引用r,就是p指向的对象,将i的值改为0

//从右往左读r的定义。r是引用,int *是引用的对象的类型,即整形指针。

2.4const限定符

初始化和const

默认状态下,const对象仅在文件内有效

当以编译时初始化的方式定义一个const对象时,

const int bufSize = 512;

编译器将在编译过程中把用到该变量的地方替换成对应的值。(编译器会找到代码中用到bufSize的地方用512替换。)

为了执行上述替换,编译器需要知道变量的初始值。如果程序包含多个文件,则每个用了const对象的文件都必须得访问到它的初始值才行。因此,每个用到变量的文件都要有对它的定义。(因此,默认const对象仅在该文件内有效)

若要在多文件共享const变量,解决办法是添加extern关键字,无论是声明还是定义。

extern const int bufSize=fcn();//定义并初始化bufSize,需要extern才能被其他文件使用。

extern const int bufSize;//在头文件的声明,指明bufSize不是文件独有。

2.4.1 const的引用

对常量的引用不能被用作修改它所绑定的对象。

const int ci = 1024;  //常量

const int &r1 = ci;  //r1是个引用,绑定的对象是个const int

int &r2 = ci;  //错误.r2是个引用,需要绑定的是int,但是ciconst int.

//对于非constint,可以用const引用取绑定他;

//对于constint,不能用非const引用绑定他。权限冲突,const int对象本身不可修改,引用也无权修改。//权限可以少,但是不能多。

//常量引用是对const的引用。

2.4.2指针和const

指向常量的指针,不能用于改变其所知对象的值。要想存放常量对象的地址,只能使用指向常量的指针。

指向常量的指针或引用,不过是自以为是,它们觉得指向了常量,自觉地不去改变对象的值。

const指针

指针是对象,引用不是。允许把指针本身定义为常量。常量指针必须初始化。

*放在const关键前,用以说明指针是个常量(不变的是指针的值,而不是所指对象的值)

int errNumb0;

int *const curErr = &errNumb;  //常量指针curErr,将一直指向errNumb

const double pi = 3.14159;

const double *const pip = π  //指向常量pi的 常量指针pip

2.4.3 顶层const

顶层const表示指针本身是个常量;

底层const表示所指对象是个常量。//二者是相互独立的。

int i = 0;  //

int *const p1 = &i;  //不能改变p1的值,顶层const

const int ci = 42;  //不能改变ci的值,对象ci本身是const,顶层const

const int *p2 = &ci;  //允许改变p2的值,底层const指对象是const int,不能改所指对象的值。(自以为是)

const int *const p3 = p2;  //不能改变p3的值,也不能改变所指对象的值。

const int &r = ci;  //用于声明引用的const都是底层const

对执行对象拷贝操作时,顶层const没有限制。

对底层const有限制:

int *p = p3;  //错误。p3包含底层const的定义而p没有。p可能修改p3所指的对象。

p2 = p3;  //p3const指针,不改指向。所指对象ciconst intp2可以接收p3,因为底层const都是const int。且p2指向是非const的,可以改变指向

p2 = &i;  //p2可以改变指向。p2指向const int 是自以为是!自觉不改其值而已。

int &r = ci;  //错误。引用r不自觉地会该const int

const int &r2 = i;//正确。自以为是。

2.4.4 constexpr和常量表达式

常量表达式,值不变,且在编译过程就能得到结果的表达式。

constexpr 变量

声明为constexpr类型,以便由编译器验证

指针和constexpr

如果constexpr声明中定义了一个指针,则只是对指针const,所指对象不限制。顶层const

2.5.1类型别名

2.5.2auto类型说明符

C++11引入auto类型说明符,用它让编译器分析表达式所述的类型。auto让编译器通过初始值推算变量的类型。

符合类型、常量和auto

编译器推断auto类型有时和初始值的类型不完全一样,编译器会适当改变使其更符合初始化规则。

首先,当引用被用作初始值时,真正参与初始化的其实是引用对象的值。

其次,auto一般会忽略顶层const,保留底层const。当初始值是指针常量时。

const int ci  = i, &cr =ci;

auto b = ci;

auto c = cr;

atuo d = &i;

auto e = &ci;

2.5.2auto类型说明符

C++11引入auto类型说明符,用它让编译器分析表达式所述的类型。auto让编译器通过初始值推算变量的类型。

符合类型、常量和auto

编译器推断auto类型有时和初始值的类型不完全一样,编译器会适当改变使其更符合初始化规则。

首先,当引用被用作初始值时,真正参与初始化的其实是引用对象的值。

其次,auto一般会忽略顶层const,保留底层const。当初始值是指针常量时。

const int ci  = i, &cr =ci;

auto b = ci;  //b是一个整数(ci的顶层const被忽略)

auto c = cr;  //c是一个整数(crci的别名,ci本身是一个顶层const)

atuo d = &i;  //d是一个整形指针(整数的地址就是指向整数的指针)

auto e = &ci;  //e是一个指向整数常量的指针(对常量对象去地址是一种底层const)

如果希望推断出auto类型是顶层const,需要手动加:

const auto f = ci;

设置auto的引用时,初始值的顶层const属性仍然保留。

auto &g = ci;        //g是const int&,不能为g赋值

auto &h = 42;   //错误//h是int&,不能绑定字面值

const auto &j = 42;  //正确.//j是const int&

2.5.3decltype类型指示符

希望从表达式的类型推断出要定义的变量的类型,但是不想用表达式的值。

declytype的作用是选择并返回操作数的数据类型。

编译并不实际调用函数f,却能使用调用f时的返回值类型。

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

decltype处理顶层const和引用的方式和auto不同。如果decltype使用的表达式是变量,则返回变量的类型。

decltype和引用

int i = 42, *p = &i, &r = i;

decltype(r+0 b);  //正确。加法的结果是int,因此b是个未初始化的int

decltype(*p) c;  //错误。cint&,必须初始化。

//r是个引用,因此decltype(r)的结果是引用类型。如果想让结果类型是r所指的类型,可以把r作为表达式的一部分如r+0

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

decltype((i)) d;  //错误。dint&,必须初始化

decltype(i) e;  //正确。e是未初始化的int

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值