C++Primer(第二章2.1,2.2,2.3,2.4)总结

来源:互联网 发布:电脑数据传输线 编辑:程序博客网 时间:2024/05/16 00:52

2.1
wchar_t 16位
char16_t 16位
char32_t 32位
long double 扩展精度浮点数 10位有效数字

在算数表达式中不要使用char和bool,只有在存放字符或者布尔值的地方使用它们,因为类型
char在一些机器上是有符号的,而在另一些机器上又是无符号的。如果一定使用char类型请指明是unsigned char 还是signed char

执行浮点运算选用double,这是因为float通常精度不够而且双精度浮点数和单精度浮点数的计算代价相差无几,事实上,对于某些机器来说,双精度的运算甚至比单精度还快,long double提供的精度在一般情况下是没有必要的,况且它带来的运行时消耗也是不容忽视的。

当我们给无符号数类型一个超出它表示范围的值时,结果是初始值对于无符号类型表示数值总数取模后所得到的余数。

for(unsigned u=10;u>=0;–u)

来看看当u等于0时发生了什么,这次迭代输出0,然后继续执行for语句里的表达式,表达式–u从u当中减去1,得到的结果-1并不满足,无符号数的要求,此时-1被自动转换成4294967295

2.2
C++程序员们一般在很多场合都会使用对象(object)这个名词,通常情况下,对象是指一块能存储数据并拒有某种类型的内存空间。

在C++语句中,初始化是一个异常复杂的问题。在C++语言中间,初始化和赋值是两个完全不同的操作。
初始化不是赋值,初始化的含义是在创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来替代。

列表初始化:如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器将报错。

分离式编译:该机制允许程序分割为若干个文件,每个文件都可被独立编译。
声明:使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。
而定义负责创建与名字关联的实体。

任何包含了显示初始化的声明即成为定义,我们能给由extern关键字标记的变量赋一个初始值,但是这样做也就抵消了extern的作用。extern语句包含初始值就不再是声明而变成定义了。
变量能且只能被定义一次,但是可以被多次声明。

int &refVal4=10 错误:引用类型的初始值必须是一个对象

double dval=3.14;
int &refVal5=dval;//错误:此处引用类型的初始值必须是int类型对象。

指针与引用不同点:
1.指针本事就是一个对象,允许对指针赋值和拷贝,而且指针的生命周期内它可以先后指向几个不同的对象。
2.指针无须在定义时赋初值。

指针的值(即地址)应属下列4种状态之一:
1.指向一个对象。
2.指向紧邻对象所占空间的下一个位置
3.空指针,意味着没有指向任何对象
4.无效指针,也就是上述情况之外的其他值

试图拷贝或以其它方式访问无效指针的值都将引发错误,编译器并不负责检查此类错误,这一点和试图使用未进初始化的变量是一样的。访问无效指针的后果无法预计。

尽管第二种和第三种形式的指针是有效的,但是使用同样受到限制,显然这些指针没有指向任何具体的对象,所以试图访问此类指针(假设)对象的行为是不被允许的。如果这样做了,后果也无法预计。

解引用操作仅适用于那些确实指向了某个对象的有效指针。

空指针
三个生成方法:

int *p1=nullptr;//等价于int*p1=0;int *p2=0;//直接将p2初始化为字面常量0int *p3=NULL//需要首先#include cstdlib等价于int *p3=0;

nullptr是c++11新标准刚刚引入的一种方法。nullptr是一种特殊类型的字面值,它可以被转换成任意其他类型的指针类型

预处理器是运行于编译过程之前的一段程序就可以了,预处理变量不属于命名空间std,它由预处理器负责管理,因此我们可以直接使用预处理变量而无须在前面加上std::。

而int变量直接赋给指针是错误的操作,即使int变量的值恰好等于0也不行。
int zero=0;
pi=zero;

指针和引用都能提供对其他对象的直接访问,然而在具体实现细节上二者有很大不同,其中最重要的一点就是引用本身并非一个对象。一旦定义了引用,就无法令其再绑定到另外的对象,之后每次使用的这个引用都是访问它最初绑定的那个对象。

利用void*指针能做的事儿比较有限,拿它和别的指针比较,作为函数的输入或输出,或者赋给另外一个void*指针,不能直接操作void*指针所指的对象。

int *p1,p2;//p1是指向int的指针,p2是intint *p;int *&r=p;//r是一个对指针p的引用

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

const int ci=1024;
int &r2=ci;//错误:试图让一个非常量引用指向一个常量对象。

double dval=3.14;cosnt int &ri=dval;等价于const int temp=dval;const int &ri=temp;

ri绑定了一个临时量对象,所谓临时量对象就是当编译器需要一个空间来暂存表达式的求值结果时创建的一个未命名的对象,C++程序员们常常把临时量对象简称为临时量。上面在c++中被归为无效。

和常量引用一样,指向常量的指针也没有规定其所指对象必须是一个常量。所谓插向常量的指针仅仅要求不能通过该指针改变对象的值,而没有规定那个对象的值不能通过其他途径改变。

用名词顶层const表示指针本事是一个常量,而用名词底层const表示指针所指的对象是一个常量。

更一般的,顶层const可以表示任意的对象是常量,这一点对任何数据类型都适用,如算术类型,类,指针等,底层const则与指针和引用等复合类型的基本类型部分有关,比较特殊的是,指针类型即可以是顶层const也可以是底层const,这一点和其它类型区别明显、
当执行对象的拷贝操作时,常量是顶层const还是底层const区别明显,其中顶层const不受什么影响。
执行拷贝操作并不会改变被拷贝对象的值,因此,拷入和拷出的对象是否是常量都没什么影响。
另一方面底层const的限制却不能忽略,当执行对象的拷贝操作时,拷入和拷出的对象具有相同的底层const资格,或者两个对象的数据类型必须能够转换,一般非常量可以转成常量。反之不行。
常量表达式:是值不会改变并且在编译过程就能得到计算结果的表达式。
const int sz=get_size();sz不是表达式,尽管sz本身是一个常数,但它的具体指到运行时才能获取到,所以也不是常量表达式。

constexpr:
尽管constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象。

函数体内定义的变量一般来说并非存放在固定地址中,因此constexpr指针不能指向这样的变量。相反的,定义所有函数外的对象其地址固定不变,能用来初始化constexpr指针,允许函数定义一类有效范围超出函数本身的变量,这类变量和定义在函数体之外的变量也有固定地址,因此constexpr引用能绑定到这样的变量上,constexpr指针也能指向这样的变量。

constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针对象无关,
constexpr const int *p=&i;
p是常量指针,指向整型常量i;

0 0
原创粉丝点击