记录刷题的细节内容,算法与c++特性
1.static定义静态局部变量特点:
全局数据区分配内存;
执行首次初始化后,之后函数调用不在初始化
无显示初始化后,自动初始化为0
2.局部变量存在于堆栈中,全局变量存在于(静态区)中,动态申请数据存在于(堆)
3.模板
template<typename 数据类型参数标识符>(typename 和 class 没区别)
<返回类型><函数名>(参数表)
{
函数体
}
模板形参不能为空。一但声明了模板函数就可以用模板函数的形参名
声明类中的成员变量和成员函数,即可以在该函数中使用内置类型的地方
都可以使用模板形参名
example:
template<class T> struct{
static void foo(T op1, T op2){
cout<<op1<<op2;
}
};sum <int>::foo(1,3) //一个完整的例子
4.c++虚函数概念(弱点)
C++中的虚函数的作用主要是实现了多态的机制。基类定义虚函数,子类可以重写该函数。
当子类重新定义了父类的虚函数后,当父类的指针指向子类对象的地址时,[即B b; A a = &b;]
父类指针根据赋给它的不同子类指针,动态的调用子类的该函数,而不是父类的函数,而如果使用了virtual关键字,程序将根据引用或指针指向的 对 象 类 型 来选择方法,否则使用引用类型或指针类型来选择方法。
B b;
A *pa;
pa = &b;
A *pa2 = newA;
pa->FuncA(); ( 3) pa=&b动态绑定但是FuncA不是虚函数,所以FuncA called
pa->FuncB(); ( 4) FuncB是虚函数所以调用B中FuncB,FuncBB called
pa2->FuncA(); ( 5) pa2是A类指针,不涉及虚函数,
调用的都是A中函数,所以输出 FuncA called FuncB called
5.vector的函数erase();
一次只删除一个元素,返回一个迭代器指针,指向下一个元素。
6.默认只读模式打开文件
ios (iostream) : app和ios : app|ios : out,是一个意思,只能输出不能输入
7.数组的定义区别理解
int *s[8];
定义一个指针数组,该数组中每个元素是一个指针,
每个指针指向哪里就需要程序中后续再定义了。
int (*s)[8];
定义一个数组指针,该指针指向含8个元素的一维数组(数组中每个元素是int型)。
区分int *p[n]; 和int (*p)[n];
就要看运算符的优先级了。
int *p[n]; 中,运算符[ ]优先级高,先与p结合成为一个数组,
再由int*说明这是一个整型指针数组。
int (*p)[n]; 中( )优先级高,
首先说明p是一个指针,指向一个整型的一维数组。
8.函数模板
函数模板必须由编译器根据程序员的调用类型实例化为可执行的函数。
类模板的成员函数都是函数模板
没使用过的成员函数(即函数模板)不会被实例化
9.双目运算符的判断机制
&&和||的判断机制,A&&B,若A为假,直接返回false,B不执行,若A为true,继续执行B;A||B,若A为true,直接返回true,B不执行
10. c++中的switch
1.switch后面的“表达式”,可以是int、char和枚举型中的一种,不能是float型变量
2.case后面必须是“常量表达式”,表达式中不能包含变量
3.switch后的表达式加了分号 ;非法
11.unsigned
unsigned为无符号整数,取值范围位0-255,永远不可能小于零,最好不要做控制条件。
12.派生类继承编译
派生类继承(public, private)基类成员后,
继承的基类成员在派生类中的相应权限的改变。
public 继承,基类的各类(public, protected, private)成员
在派生类中权限与原来在基类时保持一致;
private 继承,基类的各类成员在派生类中权限均变为private.
故C类中的print调用A::print(),
因为A::print()此时在C类中为private等级,
所以不能被C类任何成员所访问,故不能通过编译
13.引用
引用是一个对象的别名,引用类型引用(refer to)另外一种类型。如int &refVal = val;
- 1、引用必须初始化
- 2、引用与其初始值是绑定bind在一起的,而不是拷贝区域
- 3、值传递以拷贝实参,传递给形参。
14.C++ STL (Standard Template Library) string库中的风格比C风格的字符串更加安全、高效。
15.while与for
- while: 为不确定迭代的次数时使用,例如读取数据
- for: 确定范围时使用,也可以省略初始值、条件、已经表达式
16.异常问题
throw、try、异常块;
throw: 异常表达式表示其遇到无法处理的问题,引发raise的异常
try: try和一个多个catch字段配合结束,一般的try抛出的某个异常会被某个catch捕获处理,故catch称为异常处理代码。
17、class与struct区别
在于访问权限
class
第一个访问说明符之前的成员为private
struct
第一个访问说明符之前的成员为public
18.使用非成员版本的swap
是一个好习惯
swap(c1,c2)==c1.swap(c2)
,但是使用最好使用前者。
19.泛型算法
头文件#include<algorithm> ||#include<numeric>
标准库中提供了超过100个算法,所以说阅读源代码非常重要。
copy (ilst.begin(), ilst.end(), back_inserter(ivec))
copy函数
20.关联容器(hash、map、set)
map
:map<string, int> word_count = {{"a", 1}, {"b", 2}};
set
:set<string> exclude = {"the", "a"};
- unordered_map(hash组织map)
- unordered_set(hash组织set)
21.字符指针
char *str[3] = {"stra","strb","strc"}
;是一个指针数组; char *p = str[0]
;实际上p指向第一个字符串,所以字符串加1,则指向字符串的下一个字母,而并非是下一个字符串
22.static 与 非static ,全局变量与局部变量
无论是static还是非static的全局变量,如果不加限制随意访问的话易出现同步问题。
无论是static还是非static的局部变量,每个线程都是私有的,其他线程不会对其进行干扰。
23.C/C++中main函数为入口函数,为必须存在函数。
24.throw、catch、try
-
throw是抛出异常关键字,try是尝试执行可能有异常代码的关键字,catch是捕获异常的关键字
-
可能抛出异常的代码块都应该放在try代码块中
-
catch捕获相应的异常,可以有多级catch代码块来捕获不同级别的异常
-
被捕获的异常可以再次抛出
25.线程
线程使用了
wait
方法,会强行打断当前操作,进入阻塞(暂停)状态,然后需要notify
方法或notifyAll
方法才能进入就绪状态。
26.枚举变量
枚举变量是全局变量的情况下,枚举值的缺省值是0,不是枚举的第一个值。其他情况,其值是不定的,而且不限定于所列出的枚举值。
全局变量时初始化为0,局部变量时初始化为随机值。
26.unsigned
移动的1代表的是一个单位量
unsigned
p1+5=p1+5*1=p1+5*sizeof(unsigned char)
=p1+5*1=0x801000+ox5=0x801005
p2+5=p2+5*1=p2+5*sizeof(unsigned long)
=p1+5*4=0x810000+20=0x810000+0x14=0x810014
27.数组、指针、字符串的长度计算
对字符串进行sizeof
操作的时候,会把字符串的结束符\0
计算进去的
进行strlen
操作求字符串的长度的时候,不计算\0
的。
数组作为函数参数传递的时候,已经退化为指针了,Func
函数的参数str_arg
只是表示一个指针,那个str_arg[]
括号中的数值不起任何作用。
28.强制类型转换后指针的类型。
char str[] = "glad to test something";
char *p = str;
p++;
int *p1 = reinterpret_cast<int *>(p);
p1++;
p = reinterpret_cast<char *>(p1);
printf("result is %s\n", p);
p的类型为char *,p++
后p
指向str
数组的第2个元素即字母“l”的位置。
p1的类型为int *,p1++
后p1
指向的位置增加4个字节,
指向str
数组中的第6个元素即字母t
的位置。
因此最后p的内容为to test something
。
29.类
- 在类中,如果为空类,则类占用1个字节
- 一旦类中有其他的占用空间成员,则这1个字节就不在计算之内,
- 一个类只有一
int
则占用4字节而不是5字节。 - 如果只有成员函数,则还是只占用1个字节,因为类函数不占用空间
- 但是由于虚函数存在一个虚函数表,需要4个字节,数据成员对象如果为指针则为4字节,注意有字节对齐,如果为13字节,则进位到16字节空间
29.类
- 在类中,如果为空类,则类占用1个字节
- 一旦类中有其他的占用空间成员,则这1个字节就不在计算之内,
- 一个类只有一
int
则占用4字节而不是5字节。 - 如果只有成员函数,则还是只占用1个字节,因为类函数不占用空间
- 但是由于虚函数存在一个虚函数表,需要4个字节,数据成员对象如果为指针则为4字节,注意有字节对齐,如果为13字节,则进位到16字节空间
30.buffer
函数char *myString()中没有使用new或者malloc分配内存,
所有buffer数组的内存区域在栈区
随着char *myString()的结束,栈区内存释放,字符数组也就不存在了,
所以会产生野指针,输出结果未知
31.动态分配在堆区,其他的均不在堆区。
32.操作系统中用户态切换到内核态的 3 种方式
a. 系统调用
b. 异常
c. 外围设备的中断
33.函数嵌套
若有如下函数定义,这种嵌套定义根本算不出结果,所以函数嵌套定义肯定不行
int f(int a)={return a+f1(a);}
int f1(int b)={return b+f(b);}
无法算出结果故定义嵌套不使用
34.静态变量初始化
在C++中,类的静态成员(static member)必须在类内声明,在类外初始化
class A
{
private: static int count ; // 类内声明
};
int A::count = 0 ; // 类外初始化,不必再加static关键字
为什么?因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员,这是矛盾的。
能在类中初始化的成员只有一种,那就是静态常量成员。
这样不行
class A
{
private: static int count = 0;
静态成员不能在类内初始化
};
class A
{
private: const int count = 0;
常量成员也不能在类内初始化
};
class A
{
private: static const int count = 0;
静态常量成员可以在类内初始化
};