求职之C++牛客网刷题总结

把平时在印象笔记上记录的内容分享一下。。。

1.必须使用初始化列表的情况:
     1>常量成员const:常量成员只能初始化不能赋值
     2>引用类型:必须在定义时初始化,并且不能重新赋值
     3>没有默认构造函数的类类型:因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化。

2.小端模式
高地址存放高位,低地址存放低位

3.结构体和联合体的区别
相同点:都可以构造数据类型
不同点:
结构体变量所占内存长度是各成员占的内存长度的总和。
共同体变量所占内存长度是各最长的成员占的内存长度。几个不同类型的变量共占一段内存。所有成员不能同时存在。
struct 与 Union主要有以下区别:

1. struct和union都是由多个不同的数据类型成员组成, 但在任何同一时刻, union中只存放了一个被选中的成员, 而struct的所有成员都存在。在struct中,各成员都占有自己的内存空间,它们是同时存在的。一个struct变量的总长度等于所有成员长度之和。在Union中,所有成员不能同时占用它的内存空间,它们不能同时存在。Union变量的长度等于最长的成员的长度。

2. 对于union的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于struct的不同成员赋值是互不影响的。


union不支持继承,不能定义虚函数,默认访问权限是public,成员类型不能是静态的和引用的。

4.const ,volatile
const int i=0;
之后通过指针修改i的值后,在编译时变量i的值为已知的,编译器直接将printf输出的变量i替换为0.
如果i是volatile const int 类型,则编译器不会对变量i做优化,printf输出结果就为改后的值。

5.fork
每一个fork()出来的新进程与父进程 使用相同的代码段,并 复制父进程的数据段和堆栈段

6.n个节点的完全二叉树
n0是度为0 的节点总数(即叶子节点数)
n1是度为1的节点总数
n2是度为2的节点总数

由n=n0+n1+n2
n-1=n0*0+n1*1+n2*2
=====>n0=n2+1  (二叉树通式)

对于完全二叉树,n1=1 or 0
n0=(n+1)/2 或 n/2

6.静态绑定,动态邦定
静态绑定是指指针指向声明时的对象。
动态邦定是指指针指向引用的对象。

7.#define
代码在遇到#define时,是直接把define定义的内容替换掉源代码里的内容

8.枚举类型enum
枚举的默认类型是int
所有枚举类型的size是 4

9.虚函数
要正确实现虚函数,只能用一个基类的指针或者引用来指向派生类对象。

10.未定义的行为
     1>同一运算符中多个操作数的计算顺序
     2>函数各参数的求值顺序
     3>通过指针直接修改const常量的值
     4>除0
     5>某些指针操作也会导致未定义行为
     6>需要有返回值的函数却没有return语句

11.数组首地址
数组首地址是常量,不能被赋值

12.指针数组,数组指针
[]的优先级比*高。
p先与[]结合就是数组,先与*结合就是指针。

13.a与&a的区别
&a是整个数组的首地址,a是数组元素的首地址。值相同,但意义不同。

&a+1=&a+sizeof(a)*1  即下一个数组的地址
*(a+1)表示a[0]的首地址的下一个地址,即a[1]的地址

14.联合体union
     1>联合体变量砸定义时可以初始化,但联合体的成员的在定义时不能初始化。
     2>联合体的成员共址,某一时刻只有当前成员有效。
     3>联合体变量战友的内存大小是联合体中最长成员所占的存储空间。

15.静态数据成员
static 成员变量的内存空间既不是在声明类时分配,也不是在创建对象时分配,而是在初始化时分配

static 成员变量与对象无关,不占用对象的内存,而是在所有对象之外开辟内存,即使不创建对象也可以访问

类的静态成员不能在类内初始化。
类名和对象都可以直接调用静态数据成员。

16.绝对不重新定义继承各来的缺省参数值
virtual函数是动态绑定,而缺省参数是静态绑定。调用一个定义于派生类内的虚函数的同时,却是用基类为它所指定的缺省参数值。

17.逻辑结构,存储结构
逻辑结构:线性逻辑,非线性逻辑
存储结构:线性,链式,散列,索引

18.传递指针值
要是函数能修改指针的值,必须要向该函数传递指针的指针。
如果只是传递指针的值,则是生成了一个指针副本(但指针指向的位置相同)

19.函数默认参数
默认参数是从左往右依次赋值。
在定义函数原型时,若一个参数有默认值,后面的参数必须有默认值。

20.二维数组指针
int sec[2][3]={1,2,3,4,5,6};
int **p=sec;
则**p=sec[0][0];
*p=sec[0];
*(p+n)=sec[n];
*(*(p+n)+m)=sec[n][m]

21.默认拷贝构造函数  浅拷贝

22.封装 继承 承载 覆盖 隐藏
封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或对象操作,对不可信的进行隐藏。
继承:可以使用基类的所有功能,并可以在不重新编写类的情况下对功能进行扩展。
重载:同一个类中定义的同名函数,而且参数类型和个数要求不同。
覆盖:派生类覆盖基类中的同名函数,要求参数个数,类型,返回类型相同,而且基类的函数必须是虚函数。
隐藏:派生类中的函数屏蔽了基类中的同名函数。而且函数在基类中不是虚函数。

23.构造函数的调用顺序
先调用父类中的构造函数,再调用成员对象的构造函数,最后调用自己的构造函数。
析构过程与上面相反。

24.虚函数
有虚函数的类,其对象的前4个字节是虚表指针

25.malloc 内存泄漏
内存泄漏的只要原因是在程序中动态申请了一块内存,使用完后没有及时释放。从而导致程序占用大量内存。
malloc申请到的是虚拟地址

26.私有的析构函数
将析构函数定义为私有,则这个类只能通过new来创建对象。
编译器在为类分配栈空间时,会先检查类的析构函数的访问性,除了析构函数,只要是非静态的函数,编译器都会进行检查,如果类的析构函数是私有的,则编译器不会在栈空间上为类分配内存。

构造函数设为私有,可以阻止类实例化。(童谣可以阻止类实例化的还有纯虚函数)

27.this指针
this指针是常量指针,不允许被修改。

28.左值和右值
若能对表达式取地址,则是左值,否则为右值。
左值能出现在等号左边和右边
右值只能出现在等号右边

在C++中,临时量(右值)可以被传递给函数,但只能被接收为const &类型。

非常量左值引用(double &r=i;)只能绑定到非常量左值,不能绑定到常量左值,非常量右值和常量右值。
非法: int &r=3;  非常量引用的初始值必须为左值。

常量左值引用(const double &r=i;)可以绑定到所有类型的值,包括非常量左值,常量左值,非常量右值,常量右值。
合法:const int &r=3;

29.C++是静态数据类型语言,类型检查发生在编译时。

30.类型转换
当一个算术表达式中既有无符号数又有int值时,int值会转换成无符号数。
负数转换成无符号的数:该负数加上无符号数的模(即变成补码形式:取反再加一)

31. 在类的成员函数中调用delete this是合法的。类对象的内存空间被释放,在之后的其他函数调用中,只要不涉及到this指针的内容,都能正常运行。否则出现不可预期的问题。

在类的析构函数中调用delete this,会导致堆栈溢出。因为delete的本质是:为将被释放的内存调用一个或多个析构函数,然后释放内存从而造成无限递归,堆栈溢出。

32.声明与定义
声明:是的名字为程序所知,一个文件如果想要使用别处定义的名字必须包含对那个名字的声明。 声明规定了变量的类型和名字。                             告诉编译器这个名字是什么类型(函数?变量?其他)
定义:负责创建与名字关联的实体。 申请存储空间,也可能为变量赋初值。

声明可以有多次,定义只能有一次。

33.const对象只能调用const类型成员函数。
虚函数不能是内联函数、静态成员函数,构造函数。

34.const和static修饰全局变量的效果是一样的:不能用extern在其他模块中调用

35.指针和const
存放常量对象的地址,只能使用指向常量的指针。
允许一个指向常量的指针指向一个非常量的对象。
指向常量的指针:不能通过该指针改变对象的值。
const指针必须初始化:一旦初始化,其值(存放是地址)就不能再改变。

36.顶层const和底层const
     1>*左边的是底层const,*右边是的顶层const
     2>用于声明引用的const都是底层const
     3>当执行对象的拷贝操作时,拷入和拷出对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。
     4>constexpr把它所定义的对象置为了顶层const(常量指针)
     5>对常量对象取地址是一种底层const

 37.析构函数  虚函数
析构函数可以是虚函数,但是析构函数中不要调用虚函数。在构造函数中也不要调用虚函数。
在析构函数中不要调用虚函数的原因:因为析构函数是先析构掉派生类,在析构基类。若在基类的析构函数中调用了虚函数,根据动态绑定,会导致其调用已经析构了的子类对象里的函数,发生危险。
在构造函数中不要调用虚函数的原因:在构造函数里面调用的虚函数不是虚函数,只会静态绑定。

38.运算符的求值顺序
逻辑与,逻辑或,条件(?:)和都好运算符的计算顺序是从左往右。

39.%和/运算符
m%n的计算结果符号与m的符号相同
m/n的结果符号与m和n符号有关。

40.类型转换
在大多数表达式中,比int类型小的整数首先提升为较大的整数类型。
当表达式中既有浮点数也有整数类型的时候,整数类型转换成相应的浮点类型。
运算对象一个无符号类型,一个有符号类型
     1>无符号大于等于带符号:带符号转换为无符号类型
     2>否则,若无符号的所有值都能存在带符号类型中,则无符号—》有符号,不然带符号—》无符号

41.尽量使用常量引用
普通的引用极大限制函数能接受的实参类型。

42.返回引用的函数是左值的,意味着这些函数返回的是对象本身,而不是对象的副本。

43.常量函数
紧跟在参数列表后面的const表示this是一个指向常量的指针。(this本身就是一个常量指针)这样的成员函数叫做常量成员函数。
在一般情况下,this是一个指向非常量的常量指针。

44.vector

reserve是容器预留空间,但并不真正创建元素对象,在创建对象之前,不能引用容器内的元素,因此当加入新的元素时,需要用push_back()/insert()函数。

resize是改变容器的大小,并且创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。


45.优先队列priority_queue
priority_queue是基于vector实现的。
stack和queue是基于deque实现的。

46.二维数组定义一定要指明列数:编译器根据列数来进行寻址。

47.派生类和基类的相容性
不能把基类对象赋值给派生类对象,不能把基类对象的地址赋值给派生类对象的指针,不能把基类对象作为派生类兑现固定引用。
派生类对象只有在基类成员未被派生类覆盖的情况下才能访问基类中的成员。

48,移位操作
int a=1,b=32;
则a<<b的结果为1   :在移位前,为了防止移位数出界,先b&31=0,所以实际上为1<<0=1
而如果直接1<<32,其结果就是0

49.解决hash冲突的方法
开放定址法:按照某种规定的次序探查允许插入新元素的空位置。要求装填因子较小,当节点规模较大时,会浪费很多空间。不能直接删除节点,只能做标记。
拉链法:为每个散列地址建一个单链表,表中存储所有具有该散列值的同义词。平均查找时间短;单链表上的节点动态申请,适合造表前无法确定表长的情况;删除节点易于实现。缺点是节点规模较小是,指针空间相对较大。

50.dynamic_cast
作为对象继承之间的转换。
将基类对象指针(或引用)转换到继承类指针。要有继承关系dynamic_cast才会处理类型转换。
对指针进行dynamic_cast,失败则返回null,成功返回正常cast后的指针
对引用进行dynamic_cast,失败抛出异常,成功返回cast后的引用。

51.new和delete
动态分配的对象是默认初始化的。
new:分配内存,并调用对象构造函数
delete:调用对象的析构函数,并释放内存
传递给delete的指针必须是指向动态分配的内存,或者是一个空指针
在 delete后,指针变成空悬指针,指向一块曾经保存数据对象但现在已经无效的内存的指针。 可在delete后将nullptr赋予指针。

52.值初始化,默认初始化
值初始化的内置类型对象有着良好定义的值(如int是0,string是空串)
默认初始化的对象的值是未定义的。

53.合成的析构函数不会delete掉一个指针数据成员

54.需要析构函数的类也需要拷贝和赋值操作
需要拷贝操作的类也需要赋值操作

55.=default和=delete
=default显示要求编译器生成合成版本
只能对具有合成版本的成员函数使用default,比如默认构造函数和拷贝控制函数
=delete删除函数
必须出现在函数第一次声明时,可对任何函数指定=delete

析构函数是不能删除的成员。
希望阻止拷贝的类应该使用=delete

56.类的常成员函数
声明格式为:
类型说明符 函数名(参数列表) const;

57.稳定排序:插入,冒泡,归并,基数

58.虚函数的动态绑定仅在 基类指针或引用绑定派生类对象时发生。

59.让一个函数称为内联函数的方法:
隐式为在类里定义函数
显示为在函数前面加inline















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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值