二十万字C/C++、嵌入式软开面试题全集宝典九

目录

161、 空类

162、 空类会默认添加哪些东西?怎么写?

163、 标准库是什么?

164、 const char* 与string之间的关系,传递参数问题?

165、 char * 与char[]

166、 sizeof 和strlen 的区别

167、 针对char*和char[]求sizeof()

168、 new、delete、operator new、operator delete、placement new、placement delete

169、 空类的大小是多少?为什么?

170、 计算下面几个类的大小

171、 类对象的大小

172、 函数传递参数的几种方式

173、 将“引用”作为函数参数有哪些特点?

174、 你什么情况用指针当参数,什么时候用引用,为什么?

175、 大内存申请时候选用哪种?C++变量存在哪?变量的大小存在哪?符号表存在哪?

176、 为什么会有大端小端,htol这一类函数的作用

177、 静态函数能定义为虚函数吗?常函数?

178、 this指针调用成员变量时,堆栈会发生什么变化?

179、 设计一个类计算子类的个数

180、 怎么快速定位错误出现的地方


 

161、 空类

对于空类,编译器不会生成任何的成员函数,只会生成1个字节的占位符。在C++语言中的确规定了空结构体和空类所占内存大小为1,而C语言中空类和空结构体占用的大小是0(在gcc中测试为0,其他编译器不一定)。为什么C++会有这样的规定呢?
原来,C++语言标准中规定了这样一个原则:" no object shall have the same address in memory as any other variable",即任何不同的对象不能拥有相同的内存地址。如果空类对象大小为0,那么此类数组中的各个对象的地址将会一致,明显违反了此原则。
lsy注1:其实数组这个东西,往后找都是靠在第一个的基础上便宜,最后这句话就是说,你如果有多个类,都为0的话,他们就会覆盖。这也是数组的下标为什么从0开始的原因。

162、 空类会默认添加哪些东西?怎么写?

class Emptyclass {
}
1、缺省构造函数
Emptyclass();
2、析构函数
~Emptyclass();
3、拷贝构造函数
Emptyclass(const Emptyclass&);
4、赋值运算符
Emptyclass operator=(const Emptyclass&);
5、取地址运算符
Emptyclass* operator&();
6、取地址运算符 const
const Emptyclass* operator&() const;

163、 标准库是什么?

1.C++ 标准库可以分为两部分:
标准函数库:这个库是由通用的、独立的、不属于任何类的函数组成的。函数库继承自 C 语言。
面向对象类库:这个库是类及其相关函数的集合。
1.输入/输出 I/O、字符串和字符处理、数学、时间、日期和本地化、动态分配、其他、宽字符函数
2.标准的 C++ I/O 类、String 类、数值类、STL 容器类、STL 算法、STL 函数对象、STL 迭代器、STL 分配器、本地化库、异常处理类、杂项支持库

164、 const char* 与string之间的关系,传递参数问题?

1.string是c++标准库里面其中一个,封装了对字符串的操作,实际操作过程我们可以用const char*给string类初始化
2.三者的转化关系如下所示:
○1string转const char*
string s = “abc”;
const char* c_s = s.c_str();
○2const char* 转string,直接赋值即可
const char* c_s = “abc”; string s(c_s);
○3string 转char*
string s = “abc”;
char* c;
const int len = s.length();
c = new char[len+1];
strcpy(c,s.c_str());
○4char* 转string
char* c = “abc”;
string s(c);
○5const char* 转char*
const char* cpc = “abc”;
char* pc = new char[strlen(cpc)+1];
strcpy(pc,cpc);
○6char* 转const char*,直接赋值即可
char* pc = “abc”;
const char* c;
c = pc;

165、 char * 与char[]

char*指针定义的字符串只能读不能修改;char []定义的字符串可读可修改。
这是因为char *a = “abcd”; 此时"abcd"存放在内存的常量区。常量区只能读,而不可以修改。(而且这样定义是不可以的,需要这样写:const char *a = “abcd”)。
而char a[20] = “abcd”; 此时 "abcd"存放在栈区。可以通过指针去访问和修改数组内容。

166、 sizeof 和strlen 的区别

1.strlen计算字符串的具体长度(只能是字符串),不包括字符串结束符。返回的是字符个数。
2.sizeof计算声明后所占的内存数(字节大小,如果是字符串,包含/n),不是实际长度。
3.sizeof是一个取字节运算符,而strlen是个函数。
4.sizeof的返回值=字符个数*字符所占的字节数,字符实际长度小于定义的长度,此时字符个数就等于定义的长度。若未给出定义的大小,分类讨论,对于字符串数组,字符大小等于实际的字符个数+1;对于整型数组,字符个数为实际的字符个数。字符串每个字符占1个字节,整型数据每个字符占的字节数需根据系统的位数类确定,32位占4个字节。
5.sizeof可以用类型做参数,strlen只能用char*做参数,且必须以‘\0’结尾,sizeof还可以用函数做参数;
6.数组做sizeof的参数不退化,传递给strlen就退化为指针;

167、 针对char*和char[]求sizeof()

char *a;
char b[5];
sizeof(a) = 8 ; // 64位系统,8代表的是指针的大小,指针占8字节
sizeof(b) = 5 ; // 计算字符串数组的结果是真实的字符数组大小

168、 new、delete、operator new、operator delete、placement new、placement delete

1.new operator
new operator 完成了两件事情:用于申请内存和初始化对象。
例如:string* ps = new string("abc");
2.operator new
operator new 类似于C语言中的malloc,只是负责申请内存。
例如:void* buffer = operator new(sizeof(string)); 注意这里new前要有个operator。
3.placement new用于在给定的内存中初始化对象。
例如:void* buffer = operator new(sizeof(string));buffer = new(buffer) string("abc"); 调用了placement new,在buffer所指向的内存中创建了一个string类型的对象并且初始值为“abc”。
4.因此可以看出:new operator 可以分解operator new 和 placement new两个动作,是 operator new 和 placement new 的结合。与new对应的delete没有 placement delete 语法,它只有两种,分别是delete operator 和 operator delete。delete operator 和 new operator 对应,完成析构对象和释放内存的操作。而 operator delete 只是用于内存的释放,与C语言中的free相似。

169、 空类的大小是多少?为什么?

1.C++空类的大小不为0,不同编译器设置不一样,vs设置为1(作为一个标记);
2.C++标准指出,不允许一个对象(当然包括类对象)的大小为0,不同的对象不能具有相同的地址;
3.带有虚函数的C++类大小不为1,因为每一个对象会有一个vptr指向虚函数表,具体大小根据指针大小确定(32位系统指针大小为4字节,64位系统指针大小为8字节);
3.C++中要求对于类的每个实例都必须有独一无二的地址,那么编译器自动为空类分配一个字节大小,这样便保证了每个实例均有独一无二的内存地址。

170、 计算下面几个类的大小

1.class A{}; sizeof(A) = 1; //空类在实例化时得到⼀个独⼀⽆⼆的地址,所以为 1。
2.class A{virtual Fun(){} }; sizeof(A) = 4(32bit)/8(64bit) //当 C++ 类中有虚函数的时候,会有⼀个指向虚函数表的指针(vptr)
class A{static int a; }; sizeof(A) = 1;
class A{int a; }; sizeof(A) = 4;
class A{static int a; int b; }; sizeof(A) = 4;

171、 类对象的大小

1.类的非静态成员变量大小,静态成员不占据类的空间,成员函数也不占据类的空间大小;
2.内存对齐另外分配的空间大小,类内的数据也是需要进行内存对齐操作的;
3.虚函数的话,会在类对象插入vptr指针,加上指针大小;
4.当该该类是某类的派生类,那么派生类继承的基类部分的数据成员也会存在在派生类中的空间中,也会对派生类进行扩展。

172、 函数传递参数的几种方式

1、值传递:形参是实参的拷⻉,函数内部对形参的操作并不会影响到外部的实参。
2、指针传递:也是值传递的⼀种⽅式,形参是指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进⾏操作。
3、引⽤传递:实际上就是把引⽤对象的地址放在了开辟的栈空间中,函数内部对形参的任何操作可以直接映射到外部的实参上⾯。

173、 将“引用”作为函数参数有哪些特点?

1.传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。
2.使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。
3.使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。

174、 你什么情况用指针当参数,什么时候用引用,为什么?

1.使用引用参数的主要原因有两个:
程序员能修改调用函数中的数据对象
通过传递引用而不是整个数据对象,可以提高程序的运行速度
2.一般的原则:
○1对于使用引用的值而不做修改的函数:
如果数据对象很小,如内置数据类型或者小型结构,则按照值传递;
如果数据对象是数组,则使用指针(唯一的选择),并且指针声明为指向const的指针;
如果数据对象是较大的结构,则使用const指针或者引用,已提高程序的效率。这样可以节省结构所需的时间和空间;
如果数据对象是类对象,则使用const引用(传递类对象参数的标准方式是按照引用传递);
○2对于修改函数中数据的函数:
如果数据是内置数据类型,则使用指针
如果数据对象是数组,则只能使用指针
如果数据对象是结构,则使用引用或者指针
如果数据是类对象,则使用引用

175、 大内存申请时候选用哪种?C++变量存在哪?变量的大小存在哪?符号表存在哪?

1.大内存申请时,采用堆申请空间,用new申请;
2.不同的变量存储在不同的地方,局部变量、全局变量、静态变量;
3.C++对变量名不作存储,在汇编以后不会出现变量名,变量名作用只是用于方便编译成汇编代码,是给编译器看的,是方便人阅读的。

176、 为什么会有大端小端,htol这一类函数的作用

1.这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于 大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEILC51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

177、 静态函数能定义为虚函数吗?常函数?

1.static成员不属于任何类对象或类实例,所以即使给此函数加上virutal也是没有任何意义的。
2.静态与非静态成员函数之间有一个主要的区别。那就是静态成员函数没有this指针(因为this指针是指向对象的,而静态成员函数属于类,所以没有)。虚函数依靠vptr和vtable来处理。vptr是一个指针,在类的构造函数中创建生成,并且只能用this指针来访问它,因为它是类的一个成员,并且vptr指向保存虚函数地址的vtable.对于静态成员函数,它没有this指针,所以无法访问vptr. 这就是为何static函数不能为virtual.虚函数的调用关系:this -> vptr -> vtable ->virtual function

178、 this指针调用成员变量时,堆栈会发生什么变化?

1.当在类的非静态成员函数访问类的非静态成员时,编译器会自动将对象的地址传给作为隐含参数传递给函数,这个隐含参数就是this指针。
2.即使你并没有写this指针,编译器在链接时也会加上this的,对各成员的访问都是通过this的。例如你建立了类的多个对象时,在调用类的成员函数时,你并不知道具体是哪个对象在调用,此时你可以通过查看this指针来查看具体是哪个对象在调用。
3.this指针首先入栈,然后成员函数的参数从右向左进行入栈,最后函数返回地址入栈。

179、 设计一个类计算子类的个数

1.为类设计一个static静态变量count作为计数器;
2.类定义结束后初始化count;
3.在构造函数中对count进行+1;
4.设计拷贝构造函数,在进行拷贝构造函数中进行count +1,操作;
5.设计复制构造函数,在进行复制函数中对count+1操作;
6.在析构函数中对count进行-1;

180、 怎么快速定位错误出现的地方

1.如果是简单的错误,可以直接双击错误列表里的错误项或者生成输出的错误信息中带行号的地方就可以让编辑窗口定位到错误的位置上。
2.对于复杂的模板错误,最好使用生成输出窗口。多数情况下出发错误的位置是最靠后的引用位置。如果这样确定不了错误,就需要先把自己写的代码里的引用位置找出来,然后逐个分析了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子木呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值