Thinking in C++ 第一卷全书笔记

本文主要是阅读Thinking in C++ 第一卷的一些笔记。主要是一些注意点

Thinking in C++ Chapter 2

Translator:

  1. 解释器(interpreter)
  2. 编译器(complier)

编译器编译程序步骤:

  1. 预处理器(preprocessor)处理预处理指令
  2. 编译分为两遍,第一遍解析预处理代码生成节点数,在进行第二步之前进行全局优化(global optimizer),第二遍代码生成器(code generator)解析代码树生成机器语言或者汇编语言

静态类型检查在第一遍中进行

函数或者变量的声明与定义

void function();//声明
void function(){
   }//定义

extern int a;//声明
int a;//定义

连接

编译过程的最后阶段,把编译器生成的目标模块连接成可执行文件(操作系统可以识别)

Thinking in C++ Chapter 3

函数返回说明

return语句退出函数,返回到函数调用后的那点,联想栈的操作

通常函数库

由库管理器来管理对象模块,这个库管理器就是管理.lib/.a文件的

关于for循环的说明

for(initialization;conditional;step)

for循环首先执行initialization,其次判断conditional,满足则进入循环,执行完循环进行step步骤

switch说明

switch(selector){
    case integral-value:statement;break;
    ...
    defualt:statement;
}

switch中的selector必须为整数值,integral-value必须为整形数值

selector也可以为enum类型值

说明符(specifier)

用于改变基本内建类型的含义并将基本类型扩展成一个更大的集合
1. int: short int / int / long int(使用short和long时,int关键字可以省略)
2. float/double: 没有long float只有long double,即:float / double /long double
3. signed/unsigned:符号位(适用于整形和字符型)

void*指针说明

void*指针可以赋值为任何类型的地址,但是会丢失类型信息,不恰当的类型转换会导致程序崩溃

变量的有效作用域

从定义点开始,到和定义变量之前最邻近的开括号配对的第一个闭括号,也就是说作用域由变量所在的最近一对括号确定。

全局变量

全局变量的生命周期一直到程序结束,可以使用extern关键字来使用另一个文件中的全局变量

静态(static)变量

static变量优点是在函数范围之外它是不可用的,不可以轻易改变,使错误局部化,当应用static于函数名和所有函数外部变量时,它的意思是“在文件的外部不可以使用该名字”,即拥有文件作用域如

//file1.cpp
static int fs;
int main(){
    fs = 1;
}
//file2.cpp
extern int fs;//编译器不会找到file1.cpp文件中的fs,即文件作用域
void function(){
    fs = 100;
}
extern static int i;
int main(){
    cout << i << endl;
}
static int i = 0;
将出现error,即全局静态变量声明是有文件作用域的,编译器将会产生错误

连接(linkage种类)

  1. 内部连接:只对正在编译的文件穿件存储空间,为每一个标识符创建单独的存储空间,内部连接由关键字static指定
  2. 外部连接:对所有编译过的文件创建一个单独的存储空间,即将所有变量和函数包含在该空间中
    自动(局部)变量只是临时存在于堆栈中,连接器不知道自动变量,所以这些变量没有连接

预处理宏


#define PRINT(STR,VAR) \
    cout << STR << VAR << endl; \
    cout << VAR << STR <<endl

即可以像调用函数一样调用PRINT,这里预处理宏分行使用'\',宏只是展开,并替换

#define PRINT(STR,VAR) \
    cout << #STR << VAR << endl

这里'#'表示STR字符串化(stringizing),比如:
int i = 0;
PRINT(i,i); //这里输出应该是 i:0

typedef语法说明

typedef existing-type-description alias-name
  1. typedef unsinged long ulong;
  2. typedef int* intPtr
  3. typedef struct MyStruct{
    //这里是C常营的结构定义
    } MyStruct;
  4. typedef int (*fun)(int,int) //函数指针别名为fun

enum说明:

c++中对enum的检查更为严格,c中允许a++(a为color型枚举),但是c++中不允许,因为a++做了两次转换,首先将color类型转换为int,然后自增1之后,将该值在转换成color,第二次转换时非法的

Thinking in C++ Chapter 5

友元

使用friend关键字可以访问内部私有成员变量或者成员函数

struct X;
struct Y{
    void f(X*);
};

struct X{
    private:
    int i;
    public:
    void initialize();
    friend void g(X*,int); //Global friend
    friend void Y::f(X*); //struct member friend
    friend struct z;    //Entire struct is a friend
    friend void h();
}

Y::f(X*)引用了一个X对象的地址,编译器知道如何传递一个地址,不管被传递的是什么对象,地址具有固定大小,当试图传递整个对象时,编译器必须知道X的全部定义以确定它的大小以及如何传递,使用不完全类型说明(incomplete type specification),即在struct Y之前声明struct X;

嵌套友元

嵌套结构不能自动获得访问private成员权限,可以使用如下方法访问

  1. 声明嵌套结构
  2. 声明该结构是全局范围内使用的一个friend
  3. 定义该结构
const in sz = 20;
struct Holder{
    private:
    int a[sz];
    public:
    void initialize();
    struct Pointer;
    friend Pointer;
    struct Pointer{
    private:
    Holder* h;
    int* p;
    public:
    void initialize(Holder* h);
    void next();
    void previous();
    void top();
    void end();
    int read();
    void set(int i);
    };
};
void Holder::initialize(){
    memset(a,0,sz*sizeof(int));
}
void Holder::Pointer::initialize(Holder* rv){
    h = rv;
    p = rv->a;
}
...
int main(){
    Hodler h;
    Holder::Pointer hp;
    int i;
    h.initialize();
    hp.initialize(&h);
    ...
}

struct其他

//: Hadler.h
class Handler{
    struct Cheshire;
    Cheshire* smile;
    public:
    ...
};
//:~
//:Handler.cpp
struct Handler::Cheshire{
    int i;
    ...
}
...

Handler.h文件中struct Cheshire是一个不完全的类型说明或者类声明,具体类定义放在了实现文件中

Thinking in C++ Chapter 6

构造函数相应说明

class Object
{
   
public:
    Object(int number = 0);
private:
    int m_number;
};
//:~

//: main
int main(int argc, char *argv[])
{

    int i = 0;
    switch(i){
    case 0:
        Object obj1{
  1};
        break;
    case 1:            //error: cannot jump from switch statement to this case label "case 1:"
        Object obj2{
  2};   //jump bypasses variable initialization "Object obj1{1};"
        break;
    }

    return 0;
}

上述代码报错
switch回跳过构造函数的的序列点,甚至构造函数没有被调用时,这个对象也会在后面的 程序块中程序块中起作用,这里产生错误
是确保对象在产生的同时被初始化。goto也会产生这样的错误。

delete void*

当void*指向一个非内建类型的对象时,只会释

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值