备考秋招

目录

链表

指针和引用(左值引用)

左值和右值

堆和栈

堆栈溢出(stack overflow)

new和malloc的区别

面向过程与面向对象

封装,继承,多态

C与C++的区别

Struct和class的访问权限

static

C++中四种类型转换

Vector扩容问题

递增递减运算符


链表

1. 一旦找到插入点或删除点,就可以插入或删除,而不需要在内存中移动数据项。

2. 在每一次插入和删除的过程,链表结构会调整大小,不需要额外的内存代价,也不需要复制数据项。

3.STL中提供的forward_list(单向链表),能够达到最好的手写链表的性能,推荐使用,forward_list中并没有提供X.size()操作。

4. list(双向链表)或forward(单向链表)两个容器的设计目的是令容器任何位置的添加和删除操作都很快速。作为代价,这两个容器都不支持元素的随机访问,为了访问一个元素,我们只能遍历整个容器。如果程序要求在容器的中间插入或删除元素,推荐使用list(双向链表)或forward(单向链表)。

指针和引用(左值引用)

1. 指针是一块内存的地址,引用是一个对象的别名(相当于小名)。

2. 引用必须是已有对象的引用,引用必须被初始化。

左值和右值

当一个对象被用作右值的时候,用的是对象的值(内容),当对象被用作左值的时候,用的是对象的身份(内存中的位置)。

右值引用只能绑定到一个将要销毁的对象。

堆和栈

1)内容

堆中主要储存new,malloc等手工分配的动态内存,必须手动释放。

栈中内容由系统自动分配,包括函数返回地址,参数,局部变量,返回值

2)效率

栈比堆的效率高。

原因:栈是操作系统提供的数据结构,具有计算机底层的支持,分配专门的寄存器存储栈的地址,压栈入栈有专门的指令执行,而堆是由c/c++函数库提供的,机制复杂,需要一些相关内存的算法,因此效率较低。

3)拓展方向

栈是由高地址向低地址进行拓展,堆是由低地址向高地址拓展

堆栈溢出(stack overflow)

向栈中某一变量写入的字节数超过了这个变量申请的字节数,导致相邻的变量的值被改变

原因:

1. 局部数组过大

2. 递归调用层次太多,递归函数在运行时执行压栈操作,当压栈次数太多时,也会导致堆栈溢出

3 .指针或数组越界。

new和malloc的区别

1.malloc本质上是函数,new 是c++的关键字

2.malloc需要给定申请内存的大小,返回的指针需要强转。new会调用构造函数,不用指定内存大小,返回的指针不需要强转。

面向过程与面向对象

面向过程是分析出解决问题所需要的步骤,然后用函数把这些步骤实现。

面向对象是将事物抽象为对象。

封装,继承,多态

封装:

将数据和操作数据的方法结合起来,形成类。外界不可以直接访问类中的数据,只能通过方法访问。

继承:

子类从父类中得到已有的特性,是is-a的关系。

多态:

根据指针或引用对象的不同调用不同的函数。

C与C++的区别

1)设计思想

c是面向过程,c++是面向对象

2)c++在c的基础上引入了面向对象,c++具有封装,继承,多态等特性。

Struct和class的访问权限

struct的数据访问控制是public,class的数据访问控制是private

static

1)变量

函数外定义的变量为全局变量,具有外部链接性(可在其他文件中访问),在程序整个运行过程中都存在。

外部变量前面加上 static后,具有内部链接性(只在本文件中访问)。

局部变量前面加上static后为局部静态变量,只在局部作用域有效,在程序整个运行过程中都存在。

未经初始化的全局静态变量会被自动初始化为0(自动变量如果为被初始化时未定义的)。

2)函数

函数默认具有外部链接性,加上static的话编程内部静态函数(必须在声明和定义中全部都加)。

3)类的静态数据成员

类的多个对象共享static类成员,对多个对象来说,静态数据成员只存储一处,供所有对象共用。

4)类的静态函数

类的静态函数和类的静态数据成员一样,都属于类的静态成员,他们都不是类的对象成员,因此对静态成员的引用不需要对象名。静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员。

静态成员函数使用格式:

       类名::静态成员函数名()

C++中四种类型转换

 

Vector扩容问题

   我们知道,vector 在需要的时候会扩容,在 VS 下是 1.5倍,在 GCC 下是 2 倍。那么会产生两个问题:

1)为什么是成倍增长,而不是每次增长一个固定大小的容量呢?

答:采用成倍方式扩容,可以保证常数时间的复杂度,而增加指定大小的容量扩容,只能达到O(n)的时间复杂度。

2)为什么是以 2 倍或者 1.5 倍增长,而不是以 3 倍或者 4 倍等增长呢?

答:采用2倍, 1,2,4,。。。每次重新分配都大于之前分配之和,不能重用,

采用1.5倍,1,2,3,4,6,可以重用之前的内存空间

递增递减运算符

递增递减运算符必须作用于左值运算对象。

1. 前置递增(减)运算符与后置递增(减)运算符的区别,如i++,++i.

前置运算符返回的递增后的运算对象,因为返回值是左值,因此可以继续再赋值。

int main() {
	int i=0;
	cout << ++i << endl;//输出1
    ++i = 5 ;//++i后为2,然后被赋值5
	return 0;
}

后置运算符进行运算后,将初始值得副本作为返回值,返回值为右值。

int main() {
	int j = 0;
	cout << j++ << endl;   //返回初始值得副本,此处为0
	//j++ = 6;  //由于返回值为右值所以不能被赋值
	return 0;
}

2. 下列得程序会出错,出错原因:

赋值运算符的两端运算对象都用到it,并且右侧的运算对象还改变了it的值,所以该赋值语句是未定义的。编译器可能按照下的任意一种思路处理:

1)*it=toupper(*it)//如果先求左侧的值

2)*(it+1)=toupper(*it)//如果先求右侧的值

int main() {
	string a{ "hello world" };
	for (auto it = a.begin(); it != a.end() && !isspace(*it); ++it)
		*it = toupper(*it++);   //程序运行到此处会出错
	cout << a;
}

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值