C++ Primer笔记

C++ Primer笔记

大学时学的C,C++都是C98,C99标准,且学的比较基础,许多新特性、细节问题没有了解过,在此记录学习C++ Primer过程中一些要点。

类型选择建议

和C语言一样,C++的设计准则之一也是尽可能地接近硬件。C++的算术类型必须满足各种硬件特质,所以它们常常显得繁杂而令人不知所措。事实上,大多数程序员能够(也应该)对数据类型的使用做出限定从而简化选择的过程。以下是选择类型的一些经验准则:

  • 当明确知晓数值不可能为负时,选用无符号类型。
  • 使用int执行整数运算。在实际应用中,short常常显得太小而long一般和int有一样的尺寸。
  • 如果你的数值超过了int的表示范围,选用long long。
  • 在算术表达式中不要使用char或bool,只有在存放字符或布尔值时才使用它们。因为类型char在一些机器上是有符号的,而在另一些机器上又是无符号的,所以如果使用char进行运算特别容易出问题。如果你需要使用一个不大的整数,那么明确指定它的类型是signed char或者unsigned char。
  • 执行浮点数运算选用double,这是因为float通常精度不够而且双精度浮点数和单精度浮点数的计算代价相差无几。事实上,对于某些机器来说,双精度运算甚至比单精度还快。long double提供的精度在一般情况下是没有必要的,况且它带来的运行时消耗也不容忽视。

初始化

int main() {
   
    int b = 0;
    int x(0);
    int y{
   }; // 0
    int a(); // 0
    int z = {
   0};

    double ld = 3.1415926536;
    int c(ld), d = ld; // 成功转化,丢失部分值
    int a{
   ld}, b = {
   ld}; // 拒绝转化,可能丢失值

    return 0;
}

变量声明

变量的定义包括一个基本数据类型(base type)和一组
声明符。在同一条定义语句中,虽然基本数据类型只有一个,但是声明
符的形式却可以不同。也就是说,一条定义语句可能定义出不同类型的
变量。

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

基本数据类型和类型修饰符,后者是声明符的一部分。

复合声明判断类型

int i = 1024;
int *p = &i;
int *&r = p;
int *const ptr1 = &i; // 不能写ptr1=xxx
const int *ptr2 = &i; // 不能写*ptr2==xxx

要理解r的类型到底是什么,最简单的办法是从右向左阅读r的定义。离变量名最近的符号对变量的类型有最直接的影响。

  1. 离r最近的是&,因此是一个引用。声明符的其余部分用li以确定r引用的类型是什么,此例中的符号*说明r引用的是一个指针。最后,声明的基本数据类型部分指出r引用的是一个int指针。
  2. 离ptr1最近的是const,意味着ptr1本身是一个常量,下一个符号是*,表示ptr1是一个常量指针,即ptr1所指向的地址是不能变化的,最后是int,其指向的内存地址中保存的值是一个int。ptr1是一个指向整型变量的常量指针。
  3. 离ptr2最近的是*,表示ptr2是一个指针,下一个符号是int,表示该指针指向的值都类型是int,最后是const,表示其指向的int类型的值不可改变。ptr2是一个指向整型常量的指针。

编译连接过程

  1. 预处理(PreProcessing),预处理用于将所有的include头文件以及宏定义替换成其真正的内容,预处理之后得到的仍然是文本文件,但文件体积会大很多,对每个文件都要进行该操作。
  2. 完成代码替换后,将每个文件编译为.obj文件,这时候需要依次解析文件中的每个符号,在不同的文件中符号允许多次声明,但只能有一次定义
  3. 链接过程将多个目标文以及所需的库文件(.so等)链接成最终的可执行文件(executable file)。

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

编译器将在编译过程中把用到const变量的地方都替换成对应的值。为了执行上述替换,编译器必须知道变量的初始值。如果程序包含多个文件,则每个用了const对象的文件都必须得能访问到它的初始值才行。要做到这一点,就必须在每一个用到变量的文件中都有对它的定义(通过include或者其他文件或者每个文件都自己定义,因为const是不可变的,只要每个文件的const值一样,就不会有问题)。为了支持这一用法,同时避免对同一变量的重复定义,默认情况下,const对象被设定为仅在文件内有效。当多个文件中出现了同名的const变量时,其实等同于在不同文件中分别定义了独立的变量。以下是两个例子。

// 1.cpp
const int x = 100;

// main.cpp
#include <iostream>
#include 1.cpp”
int main(){
   
  std::cout << x;
  return 0;
};
  1. 处理编译1.cpp,预处理无替换代码,只声明且定义了一个const变量,因为const只有在该文件中有效,符号表中会标记该符号仅在当前文件有效。
  2. 处理编译main.cpp, #incude "1.cpp"被替换为const int x = 100,编译时x被替换为常量100,编译通过且结果正确。
  3. 链接,无变量的缺失定义和重复定义。事实上,const变量在完成替换后本身就没有什么意义了
    去掉const,即如下所示,编译通过,但是链接报错,x被重复定义。
// 1.cpp
int x = 100;

// main.cpp
#include <iostream>
#include 1.cpp”
int main(){
   
  std::cout << x;
  return 0;
};
  1. 处理编译1.cpp,预处理无替换代码,只声明且定义了一个全局变量x。
  2. 处理编译main.cpp, #incude "1.cpp"被替换为int x = 100,声明且定义了一个全局变量x。
  3. 链接,1.obj和main.obj都定义了一个全局变量x,报重复定义错误(符号允许多次声明,但只能有一次定义)。

某些时候有这样一种const变量,它的初始值不是一个常量表达式,但又确实有必要在文件间共享。这种情况下,我们不希望编译器为每个文件分别生成独立的变量。相反,我们想让这类const对象像其他(非常量)对象一样工作,也就是说,只在一个文件中定义const,而在其他多个文件中声明并使用它。解决的办法是,对于const变量不管是声明还是定义都添加extern关键字,这样只需定义一次就可以了。

// a.cpp
extern const int x = function();
// b.cpp
extern const int x;

如上述程序所示,a.cpp定义并初始化了bufSize。因为这条语句包含了初始值,所以它(显然)是一次定义。然而,因为x是一个常量,必须用extern加以限定使其被其他文件使用。b.cpp中的声明也由extern做了限定,其作用是指明x并非本文件所独有,它的定义将在别处出现。

typedef别名

typedef int *pint;
typedef 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值