C++

C++

读C++ Primer Plus

Ch1 : 预备知识

Ch2 : 开始学习C++

Ch3 :处理数据

基本类型没有绝对长度,依据不同实现而异

数据类型:

整型:char、short、int、long、long long

浮点型:float、double

新类型:

wcha_t(宽字符类型)、char16_t (16位无符号)、char32_t(32位无符号)

1
2
char16_t ch1 = u'q';
char32_t ch2 = U'\Uloveyou';

整型溢出

1
2
3
4
5
//suppose SHORT_MAX = 65535
signed short x = 32767;
x++; //x = -32768
unsigned short y = 0;
y--; //y = 65535

Q :const和#define的区别?

类型转换:

  • 种类:

    • 将一种算数类型的值赋给另一种算术类型的变量时;
    • 表达式中包含不同的类型时;
    • 将参数传递给函数时。
  • 具体规则:

    1. 初始化和赋值进行的转换,assign short to long,大范围转换成小范围可能会导致信息丢失,此时会警告
    2. 以{}方式初始化时进行的转换(C++11),不允许缩窄(即变量的类型可能无法表示赋给它的值)
    3. 表达式中的转换
    4. 传递参数的转换
    5. 强制类型转换,by (typename) value or static_cast<typename>(value),强制类型转换运算符
      1. const_cast
      2. dynamic_cast
      3. reinterpret_cast
      4. static_cast

Ch4 :符合类型

Q : new和malloc区别?

A :new是运算符,malloc是库函数,new底层是malloc实现的,new类的时候会调用类的构造函数,malloc不会。

Q : 数组名和指针的区别?

A :数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意类型的内存块。

(1)修改内容上的差别

1
2
3
4
char a[] = “hello”;
a[0] = ‘X’;
char *p = “world”; // 注意p 指向常量字符串
p[0] = ‘X’; // 编译器不能发现该错误,运行时错误

(2) 用运算符sizeof 可以计算出数组的容量(字节数)。sizeof(p),p 为指针得到的是一个指针变量的字节数,而不是p 所指的内存容量。C++/C 语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。

1
2
3
4
5
6
7
8
9
10
11
12
char a[] = "hello world";
char *p = a;
cout<< sizeof(a) << endl; // 12 字节
cout<< sizeof(p) << endl; // 4 字节,
// 计算数组和指针的内存容量
void Func(char a[100]){
cout<< sizeof(a) << endl; // 4 字节而不是100 字节
}
int tell[10];
cout<<tell<<endl; //tell = &tell[0]
cout<<&tell<<endl; // display address of the whole array
int (*ps)[10] = &tell;

Ch5 :循环和关系表达式

类型别名:

1
2
3
#define BYTE char
typedef char byte;
//typedef能处理更复杂的类型别名,比如涉及表达式的时候

cin:

cin会忽略空格和换行符, cin.get(), cin.fail(), cin.eof()

Ch6 :分支语句和逻辑运算符

处理错误输入:

1
2
3
4
5
6
7
while(!(cin >> golf[i])){
cin.clear();
while(cin.get() != '\n'){
continue;
}
cout << "Please enter a number: ";
}

Ch7 : 函数

函数指针

Ch8 : 函数 进阶

Q :引用和指针的区别?

A :引用更接近const指针,必须中创建时进行初始化,一旦与某个变量关联起来,就将一直效忠于它。

名称修饰:

根据函数原型中指定的形参类型对每个函数名进行加密。

重载解析:

决定为函数调用那个一函数定义,大致过程:

  1. 创建候选函数列表
  2. 使用候选函数列表创建可行函数列表
  3. 确定是否有最佳的可行函数

模版函数的发展:

  1. 是什么类型,C++98无法判断
  2. decltype(C++11), decltype(expression) var , makes var the same type as result of expression
  3. C++11后置返回类型
1
2
3
4
5
6
template<class T1,class T2>
auto g2(T1 x,T2 y) -> decltype(x+y)
{
...
return x+y;
}

Ch9 :内存模型和名称空间

Q :#include<>和 #inlcude””的区别?

A :使用<>编译器将在存储保准头文件的主机系统的文件系统中寻找,使用””,编译器将首先查找当前的工作目录或源代码目录,如果没有找到,就会在标准位置查找。

static的两种用法:

用于局部声明,以指出变量是无链接性的静态变量时,static表示的是存储持续性;

用于代码块外的声明时,static代表的是内部链接性。

/#ifndef :

预处理器编译指令,防止一个程序中多次包含同一个头文件

说明符和限定符:

volatile:告诉编译器

mutable:用它指出即使结构(或类)变量为const,其中某个成员也可被修改。

定位new运算符:

new的一种变体,使用时能指定要使用的位置。可以使用这种特性设置内存管理规程、处理需要通过特定地址进行访问的硬件或者特地位置创建对象。注意:如果指定的位置为静态存储区,不在delete的管辖范围之内,尝试使用delete释放该空间将会导致运行时错误。

Ch10 :对象和类

多态性:

多态性是指允许同一个函数(或操作符)有不同的版本,对于不同的对象执行不同的版本。C++支持以下两种多态性:

  1. 编译时的多态性,表现为函数名(或操作符)的重载;
  2. 运行时的多态性,通过派生类和虚函数实现。

作用域为类的常量:

  1. 在类内声明一个枚举

    1
    2
    3
    4
    5
    6
    class Bakery{
    private:
    enum {Months = 12};
    double costs[Months];
    ...
    }

    用这种方式声明枚举并不会创建类数据成员,也就是说,所有对象中都不包含枚举,另外,Months只是一个符号名称,在作用域为整个类的代码中遇到他时,编译器将用12代替他。

  2. 使用static声明

    1
    2
    3
    4
    5
    6
    class Bakery{
    private:
    static const int Months = 12;
    double costs[Months];
    ...
    }

    这将创建一个名为Months的常量,该常量与其他静态变量存储在一起,而不是存在对象中。因此,只有一个Months常量,被所有Bakery对象共享。

运算符重载

友元函数

Ch11 :使用类

Ch12 :类和动态内存分配

静态类成员:无论创建了多少对象,程序都只创建一个静态类变量副本

Ch13 :类继承

派生类和基类之间的特殊关系:

  1. 公有继承的派生类对象可以使用基类的共有方法
  2. 基类指针可以在不进行显式类型转换的情况下指向派生类对象,基类引用可以在不进行显式类型转换的情况下引用派生类对象
  3. 然而,基类指针或引用只能用于调用基类方法。==原因:==如果允许基类引用隐式地引用派生类对象,则可以使用基类引用为派生类对象调用基类的方法。这么做没有什么问题,但是如果可以将基类对象赋给派生类引用,==派生类引用能够为基对象调用派生类方法==,这么做是没有意义的,因为基类根本没有派生类方法。

为基类声明一个虚析构函数:

为了确保释放派生对象时,按正确的顺序调用析构函数。

动态联编:

编译器对非虚方法使用静态联编,对虚方法使用动态联编。

虚函数的工作原理:

虚函数表

虚函数的一些注意事项:

  • 使用virtual指出
  • 如果使用指向对象的引用或指针来调用虚方法。程序将使用为对象类型定义的方法。
  • 如果定义的类将被用作基类,则应将那些要在派生类中重新定义的类方法声明为虚的。
  • 其余:
    • 类的构造函数不能是虚函数
    • 基类的析构函数应该是虚函数,即使他不需要(当然如果类里没有虚函数就没有这个必须
    • 友元不能是虚函数,只有成员才能是虚函数
    • 若在派生类中对于某个虚函数重新定义,将会隐藏基类的声明

explicit用于转换函数,与构造函数一样,explicit允许使用强制类型转换进行显式转换,但不允许隐式转换。

valarray?的使用?

Ch14 :C++中的代码重用

has-a关系和is-a关系

包含和继承

MI(恕我直言我觉得MI这个东西太不科学了= =):虚基类以解决同一个类对象可能对应多个父对象的问题。

Ch15 :友元、异常和其他

异常处理:

  1. 使用abort()
  2. 返回错误码
  3. 异常机制(try、catch),栈解退

RTTI:

  1. dynamic_cast
  2. typeid
  3. type_info

Ch16 : string类和标准模版库

STL定义了5种迭代器:

  1. 输入迭代器
  2. 输出迭代器
  3. 正向迭代器
  4. 双向迭代器
  5. 随机访问迭代器

移动构造和移动赋值

序列容器类型:

  1. vector:通过随机访问进行快速访问
  2. list:强调元素的快速插入和删除
  3. queue
  4. deque
  5. stack
  6. array
  7. forward_list

关联容器:

  1. set
  2. multiset
  3. map
  4. multimap

无序关联容器:

  1. Unordered_set
  2. Unordered_map
  3. unordered_multiset
  4. Unordered_multimap

Ch17 :输入、输出和文件

Ch18 :探讨C++新标准

Q

  • 为什么cin要比scanf慢?
  • const常量的使用?
  • 如何判断系统是64位的还是32位的?
  • 多个cpp文件联合编译过程?
  • 编译过程
  • 函数调用实现过程?
  • C++11标准?
  • 32位系统和64位系统的指针大小不一样?
  • printf参数?
  • 运算符重载?
  • 名称空间是如何识别的?
    • 名称空间是控制访问权的一种方式
  • const、static
  • 强制类型转换
    • 可类型提升,同种类型可向高级提升,非const可以提升为const,反之不可
  • 变量命名风格
  • 运算符优先级:
    • !运算符优先级最高 > 算术运算符(乘除*, / > 加减+ , -)> 关系运算符(<= , < , > , >= , != , == ) > 逻辑运算符(&&,|| )
  • 符号整型溢出
  • 换行符
  • unicode 字符集大小,ascii码自负
  • 位运算应用
  • STL
  • 引起程序溢出的错误
  • C++变量的存储不同区域(动态存储区、静态存储区
  • iter
  • 多态、继承,三大特性,五大原则
  • how to avoid memory leak
  • pointer是否支持—操作
    • A:是的,支持,同++操作一样是移动一个指向类型的长度,两个指针可以相减,不过只在数组间的两个不同下标对应的指针管用,差值是下标差值
  • 指针名和数组名的区别:(同:都可以使用方括号表示法,可以使用解引用运算符
    • 可以修改指针的值,但数组名是常量
    • 对数组应用sizeof运算符得到的是数组的长度,对指针应用sizeof得到的是指针的长度
  • C++如何处理内存?
    • 管理数据方式:(不同:严格限制了变量的寿命
      • 自动存储,函数内部定义的常规变量
      • 静态存储,整个程序执行期间都存在的存储方式,==使用栈?==
      • 动态存储,new、delete所调用的空间,使得程序员对内存有更大的控制权,==使用堆?==
  • cin、cout如何处理字符?ios_base库的作用?
  • 命名空间和头文件的区别?
    • 【个人认为】命名空间的出现是为了解决两个文件中有相同函数命名引起的混淆,而如果只是include头文件,编译器检测到出现两个相同的函数将会报错。
  • 函数重载,重载解析实现
  • volatile?
  • ifndef语句的作用?
  • /#include 包含源代码文件会导致多重声明
  • return引用和return值有什么不一样吗?(哦哦好像懂了

附1 :头文件说明:

climits : 定义符号常量,用以表示类型的限制

cctype : 字符相关的函数软件包,可以简化诸如确定字符是否为大写字母、数字、标点符号等工作,如isalpha(), isdigit(), tolower(), toupper()

附2 :标准库类介绍

1、cout

setf()

设置输出格式

给咱来个🍰,啾咪