CS100期末Review
CS100期末Revision
写在前面:这个文档是我在复习CS100期末考试的时候整理的,主要是对于自己一些不熟悉的知识点的整理,并非对于CS100知识点的全面复习。同时,本文可能会有一些错误,如果发现错误,欢迎指出。
1. 区分底层const
和顶层const
- 顶层
const
:指针本身是个常量, 指针所指的对象不是常量(指针不可以指向别的对象,但是可以改变所指对象的值) - 底层
const
:指针所指的对象是一个常量(指针可以指向别的对象,但是不可以改变所指对象的值)
e.g.
[1].const int* const p
:第一个const是底层const,第二个是顶层const
[2].const char& operator[](int index) const
:第一个const是底层const,第二个const是加在this
指针上的底层const,表示对象的所有成员都是常量,不可以被改变!!!
Remark: 为什么对一个类要定义[]
运算符const和non-const两个版本的重载?
const对象只能调用const成员函数,而non-const对象可以调用const和non-const成员函数,所以为了让const对象也能调用[]
运算符,就要定义const版本的[]
运算符重载。如果a本身就带const,而fun不是const成员函数,那这个调用就是在试图去除底层const,这是不允许的。
2. C&C++中的运算符
/
int/int 为向零取整%
满足 (a / b) * b + a % b == a||
和&&
是短路求值:(short-circuited):先求左边,如果左边的结果能确定表达式的结果,就不再对右边求值。,
先对左边求值,再对右边求值,返回右边的值- 运算符的优先级和结合性不会决定求值顺序
e.g:f() - g() + h()
中的f()
,g()
和h()
的调用顺序是 unspecified 的。f() + g() * h()
中的f()
,g()
和h()
的调用顺序是 unspecified 的。
Remark: 只有&&
,||
,?:
,,
的求值顺序是确定的,其他的都是unspecified的。
3. 变量的声明和初始化
- 空初始化
对于全局 (global) 或者局部静态 (local static) 变量,不显式初始化的情况下执行空初始化
对于局部非静态 (local non-static) 变量,不显式初始化的情况下将持有未定义的值:你不能对它的值作任何假定,使用未定义的值的行为是未定义的行为
对于类内成员的默认初始化(调用默认构造函数)在未指定默认值时的值是未定义的值
4. 指针
- 指针的值是一个地址,这个地址指向某个对象
p + i
得到的地址是(void *)p + i * sizeof(Type)
,即和p
相距i
个Type
。- 如果指针
p1
和p2
分别指向某一个数组的下标为i
和j
的位置,则p1 - p2
- 结果是
i - j
, - 类型为
ptrdiff_t
:一个定义在<stddef.h>
里的类型,是一种带符号整数,其具体大小是 implementation-defined。
- 结果是
二维数组
- 数组指针:
int (*p)[10]
指向一个含有10个整数的数组 - 指针数组:
int *p[10]
含有10个指向整数的指针的数组
Remark: 如何理解 二维数组int a[m][n]
?
- 一个指向
int[n]
的指针,即int (*p)[n]
。 - 存放了
m
个数组的地址,每个数组有n
个int
,即int *p[m]
。(二维数组退化degrade为指向首元素int [m]
的数组)
5. 字符串
- 字符串字面值:类似这种
"abcde"
(双引号!!!)- C:类型为
char [N+1]
,其中N
是它的长度,+1
是为了放空字符。 - C++:类型为
const char [N+1]
- C:类型为
'a'
的字符串字面值类型- C:
int
- C++:
char
- C:
<string.h>
的函数
strcmp(s1, s2)
按字典序 (lexicographical order) 比较两个字符串的大小。- 如果
s1
“小于”s2
,返回一个负数 - 如果相等,返回
0
- 如果
s1
“大于”s2
,返回一个正数 - 不可以认为它的返回值 $\in{-1,0,1}$!!!
- 如果
strcpy(to, from)
将from
的内容拷贝给to
。
<string>
- 默认初始化一个
std::string
对象会得到空串,而非未定义的值! - 字符串的IO:
std::cin
会忽略开头的空白字符,直到遇到下一个空白字符为止。getline(std::cin, s)
会读入一整行,包括开头的空白字符,直到遇到换行符为止。
6. Class
this
指针:指向当前对象的指针,是一个隐式参数,只在成员函数内部使用。- 特别的,static成员函数没有this指针,以
class::static_func()
调用。
- 特别的,static成员函数没有this指针,以
- 构造函数通常是重载(Overload)的,构造函数不声明返回值类型,可以含有
return;
但不能返回一个值,但不能认为它的返回值类型是void
。- 重载匹配规则:最佳匹配(Best Match)
单例模式(Singleton)
1 |
|
继承和多态(Inheritance and Polymorphism)
- 父类的所有成员(除了构造函数和析构函数)都被继承下来,无论能否访问。(private成员也被继承下来,只是不能访问而已)
- 向上转型:
Base *p = &derived;
(由派生类指针转换为基类指针) - 向下转型:
dynamic_cast<Derived *>(p)
(由基类指针转换为子类指针):如果不能成功,dynamic_cast<T*>
返回空指针,dynamic_cast<T&>
抛出std::bad_cast
异常。
符号重载(Operator Overload)
++i
返回i
的引用,i++
返回递增前的i
的一份拷贝。++i
:class &operator++()
i++
:class operator++(int)
其中int
是一个不被使用的形参,用于区分前置和后置。
- 赋值、复合赋值都返回左侧运算对象的引用。
- IO运算符:这两个运算符只能是非成员:你无法给
std::istream
和std:ostream
添加成员。std::istream &operator>>(std::istream &, Rational &r);
std::ostream &operator<<(std::ostream &, const Rational &r);
7. 客观题知识点整理
- Hw5:
- Q4:
&a
返回lvalue,a[3]
,*a
都是rvalue。 - Q7: std::string s3(); 是函数声明,而非定义空字符串。
- Q9:
std::vector v;
声明一个vector时必须指定元素类型,或者给出足够条件使得编译器能够推断出元素类型。 - Q10: 永远不能去除底层
const
- Q12:
sizeof()
在编译时求值 - Q14:
int fun(std::vector<int>)
,int fun(std::vector<double>)
构成重载。
- Q4:
- Hw6:
- Q7:对于一个类,value-initialization就是default-initialization,调用默认构造函数(大部分情况,在某些情况下会调用zero-initialization)。
- Q8:
int* ptr = nullptr; delete[] ptr;
// 是合法的 - Q10:const成员函数的const是加在
this
指针上,所以类内的int*
指针会被视为int* const
,而非const int*
,可以修改指针指向的内容。 - Q12:编译器执行析构函数时是在函数体之后销毁成员
- Q14:Dynarray中在让
m_storage
指向新的内存之前,应该先释放原来的内存。(移动赋值和拷贝赋值) - Q18: unique_pointer只能移动,不能拷贝。
- Q19:拷贝一个shared_ptr会增加引用计数,而不会拷贝指向的对象。
CS100期末Review
http://example.com/2023/05/14/CS100期末Review/