c++ 面试题 面试题复盘

目录

  • 1. #include<filename.h>与#include"filename.h"的区别
  • 3.malloc/free 与 new delete

1. #include<filename.h>与#include"filename.h"的区别

对于#include <filename.h> ,编译器从标准库路径开始搜索filename.h,
对于#include “filename.h” ,编译器从用户的工作路径开始搜索filename.h
# 2 C++中的类与c中的struct的区别
c++ 中的struct与 c中的struct区别

a) C语言中的结构体不能为空,否则会报错

b) C语言中的结构体只涉及到数据结构,而不涉及到算法,也就是说在C中数据结构和算法是分离的。换句话说就是C语言中的结构体只能定义成员变量,但是不能定义成员函数。然而在C++中既可以定义成员变量又可以定义成员函数, C++中的结构体和类体现了数据结构和算法的结合

c) C语言的结构体中不能定义成员函数,但是却可以定义函数指针,不过函数指针本质上不是函数而是指针,所以总的来说C语言中的结构体只是一个复杂数据类型?,只能定义成员变量,不能定义成员函数,不能用于面向对象编程

d) 在C语言中结构体变量定义的时候,若为struct 结构体名 变量名定义的时候,struct不能省略。但是在C++之中则可以省略struct。

c++ 中的类与 c++中的struct区别
概念:class和struct的语法基本相同,从声明到使用,都很相似,但是struct的约束要比class多,理论上,struct能做到的class都能做到,但class能做到的stuct却不一定做的到
类型struct是值类型,class是引用类型,因此它们具有所有值类型和引用类型之间的差异
效率:由于堆栈的执行效率要比堆的执行效率高,但是堆栈资源却很有限,不适合处理逻辑复杂的大对象,因此struct常用来处理作为基类型对待的小对象,而class来处理某个商业逻辑。
关系struct不仅能继承也能被继承 ,而且可以实现接口,不过Class可以完全扩展。内部结构有区别,struct只能添加带参的构造函数,不能使用abstract和protected等修饰符,不能初始化实例字段

3.malloc/free 与 new delete

1.malloc/free为C的标准库函数,函数原型为:

void* malloc(size_t size)//参数代表字节个数
void free(void* pointer)//参数代表内存地址

new 和delete是运算符
new、delete则为C++的操作运算符,它调用的分别为赋值运算符重载operator new()和operator delete();

  1. malloc/free的使用如下
//用malloc分别开辟了1个和4个整型大小的空间和并free释放它们;
void func()
{
//开辟一个空间
int* p1=(int*)malloc(sizeof(int));
if(p1==NULL)
{
exit(1);
}
free(p1);
//开辟多个空间
int*p2=(int*)malloc(sizeof(int)*4);
if(p2==NULL)
{
exit(1);
}
free(p2);
}

new/delete如下:

void func()
{
//开辟一个空间
int* p1=new int(1);
delete p1;
//开辟多个空间
int*p2=new int[4];
delete []p2;
}

由上可知

1)malloc开辟空间类型大小需手动计算,new是由编译器自己计算;?
(2)malloc返回类型为void*,必须强制类型转换对应类型指针,new则直接返回对应类型指针;?
(3)malloc开辟内存时返回内存地址要检查判空,因为若它可能开辟失败会返回NULL;new则不用判断,因为内存分配失败时,它会抛出异常bac_alloc,可以使用异常机制;?
(4)无论释放几个空间大小,free只传递指针多个对象时delete需加[](原因在第3);
(5)malloc/free为函数只是开辟空间并释放,new/delete则不仅会开辟空间,并调用构造函数和析构函数进行初始化和清理,如下为new/delete、new[]/delete[]实现机制

即过程如上,在开辟大小会多开辟四个字节,用于存放对象的个数,在返回地址时则会向后偏移4个字节,而在delete时则会查看内存上对象个数,从而根据个数count确定调用几次析构函数,从而完全清理所有对象占用内存。

4.由上图还可以看出new/delete底层是基于malloc/free来实现的,而malloc/free不能基于new/delete实现
5.因为new/delete是操作符,它调用operator new / operator delete,它们可以被重载,在标准库里它有8个重载版本;而malloc/free不可以重载;
6.对于malloc分配内存后,若在使用过程中内存分配不够或太多,这时可以使用realloc函数对其进行扩充或缩小,但是new分配好的内存不能这样被直观简单的改变
7.对于new/delete若内存分配失败,用户可以指定处理函数或重新制定分配器(new_handler(可以在此处进行扩展)),malloc/free用户是不可以处理的。
8.最后一点对于new/delete与malloc/free申请内存位置说明,malloc我们知道它是在堆上分配内存的,但new其实不能说是在堆上,C++中,对new申请内存位置有一个抽象概念,它为自由存储区,它可以在堆上,也可以在静态存储区上分配,这主要取决于operator new实现细节,取决与它在哪里为对象分配空间。

# 4 类的多态.封装,继承的理解
从实现角度分析这个问题
封装
抽象与具体实现的封装,隐藏数据的封装,函数定义与声明的封装。
1.将类的公有接口与实现细节分开,公有接口表示的是设计的抽象组件,而将类的实现细节放在一起并将它们与抽象组件分开是一种封装。将数据隐藏在类的私有部分是一种封装,将实现细节放在私有部分是一种封装,将类的函数定义和声明放在不同文件中也是一种封装。
继承
继承可以说是一种代码复用的手段,我们在一个现有类上想扩展出一些东西的时候,不需要再次重复编写上面的代码,而是采用一种继承的思想。在派生出的子类里添加一些我们想要的数据或方法,也可以理解为从一般到特殊的过程。
继承使用
相比与函数,类提供了数据的表示方法以及类的使用方法,通常类库以源代码的形式形式提供,通过修改类的内容可以满足需求。但是继承使得派生类直接可以从基类获取其特征,也可以1. 可以再已有类的基础上添加新的功能。2. 可以给类添加数据。3. 可以修改类的方法。
总结

多态
先说运行时多态,其实是指在继承体系中父类的一个接口(必须为虚函数),在子类中有多种不同的实现,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。即通过父类指针或者引用可以访问到子类的接口(虚函数),看上去就像是一个相同的动作,会出现多种不同的结果。

# 5. 编写程序判断 bool float int 和0的关系
bool型变量

if(flag)
if(!flag)//其中flag为bool类型。

int变量

if(value==0)
if(value!=0),其中value为整型变量

浮点(float和double)变量

const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON)

指针类型变量

if(p==NULL)
if(p!=NULL)

# 6 不使用c++ 或者c 的库函数编写strcopy函数的实现
需要深入理解内存的分配

#include <stdio.h>
#include <assert.h>

char *strcpy(char *strDest,const char *strSrc)
{
    assert((strDest!=NULL) && (strSrc!=NULL));

    if(strDest==strSrc)
        return strDest;

    char *address=strDest;
    while((*strDest++ = *strSrc++)!='\0')
        ;
    return address;
}

# 7 计算sizeof 的结果

char a[30];//定义了一个长度为30的字符串数组char
b = (char)malloc(20 * sizeof(char));//定义了一个指针b,它指向一个开辟了20长度的字符数组
printf("%d",sizeof(a));//这个结果是30,也就是上面说的字符数组的长度
printf("%d",sizeof(b));//这个结果是4,因为任何指针(无论指向什么)的本身长度都是4
printf("%d",sizeof(a[3]));//这个结果是1,因为a[3]就特指数组中的一个值,比如a[0],a[1],a[2]都是1
printf("%d",sizeof(b+3));//这个结果是4,因为b是指针,你将指针挪动了3位,它所指向的地方了//(也就是那个新开辟的20大小的数组)向后挪动了3位.//但是它终究还是个指针,所有指针长度都是4
printf("%d",sizeof(*(b+4)));//这个结果是1,因为b+4将指针后移4位,指向了那个20长度字符数组中//的第4位了,而字符数组中的每一位都是一个字符而已,每个字符占1位printf("%d",sizeof(u));//这个结果是8,我记得我上学的时候老师说这种结构体的大小就和里面最大//的元素的大小一样,那doule类型占8位,所以这个就是8了所以输出的结果应该是3041418

# 8 判断数组对象返回的函数指针,通过printf输出的结果

#include<iostream>
using namespace std;
char *GetMemory(void)
{
???????char p[] = "hello word";
???????return p;
}
void Test(void)
{
???????char* str = NULL;
???????str = GetMemory();
???????//printf("%s",str);
???????printf( str);
}
int main()
{
???????Test();
???????//因为p的生命周期在GetMemory函数执行完了就被销毁了,str 指向的是个野指针
}

# 9 使用的STL容器有哪些,用过的其中的算法有哪些、
1、顺序容器:是一种各元素之间有顺序关系的线性表,是一种线性结构的可序群集。顺序性容器中的每个元素均有固定的位置,除非用删除或插入的操作改变这个位置。顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。顺序容器包括:vector(向量)、list(列表)、deque(队列)。
? 2、关联容器:关联式容器是非线性的树结构,更准确的说是二叉树结构。各元素之间没有严格的物理上的顺序关系,也就是说元素在容器中并没有保存元素置入容器时的逻辑顺序。但是关联式容器提供了另一种根据元素特点排序的功能,这样迭代器就能根据元素的特点“顺序地”获取元素。元素是有序的集合,默认在插入的时候按升序排列。关联容器包括:map(集合)、set(映射)、multimap(多重集合)、multiset(多重映射)。
? 3、容器适配器:本质上,适配器是使一种不同的行为类似于另一事物的行为的一种机制容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现。适配器是容器的接口,它本身不能直接保存元素,它保存元素的机制是调用另一种顺序容器去实现,即可以把适配器看作“它保存一个容器,这个容器再保存所有元素”。STL 中包含三种适配器:栈stack 、队列queue 和优先级队列priority_queue 。

? ? ? ?容器类自动申请和释放内存,因此无需new和delete操作。

# 10 如下算法从迭代器中消除2是否存在错误

#include<iostream>
#include<vector>
using namespace std;
typedef vector<int>IntArray;
int main()
{
???????IntArray array;
???????array.push_back(1);
???????array.push_back(2);
???????array.push_back(2);
???????array.push_back(4);
???????for (IntArray::iterator itor = array.begin(); itor != array.end(); itor++)
???????{
??????????????if (2 == *itor)
??????????????{
?????????????????????array.erase(itor);
?????????????????????//以上存在严重的错误,当erase itor后,itor变成了一个野指针,对于野指针进行操作明显是错误的。
??????????????}
???????}

原文地址:https://www.cnblogs.com/codeAndlearn/p/11827165.html

时间: 2024-08-02 01:32:45

c++ 面试题 面试题复盘的相关文章

老男孩教育-linux面试题-笔试题-1

2. 笔试题-1 2.1 新建一个用户user,密码是123456,并将其加到root组 useradd user -G root && echo "123456"|passwd --stdin user 2.2 显示当前系统的日期和时间 [[email protected] /]# date +%F 2016-08-25 [[email protected] /]# date +%X 10时16分25秒 [[email protected] /]# date +%H:

BAT笔试试题常见试题总结(持续更新。。。)

(1)试题如下: class A { int a; short b; int c; char d; }; class B { double a; short b; int c; char d; }; 在32位机器上用gcc编译以上代码,求sizeof(A),sizeof(B)分别是多少. 12 16 12 12 16 24 16 20 答:C 根据以下条件进行计算:(核心知识点:结构体的对齐方式) 1. 结构体的大小等于结构体内最大成员大小的整数倍 2. 结构体内的成员的首地址相对于结构体首地址

BAT笔试试题常见试题总结含答案(持续更新。。。)

(1)试题例如以下: class A { int a; short b; int c; char d; }; class B { double a; short b; int c; char d; }; 在32位机器上用gcc编译以上代码,求sizeof(A),sizeof(B)各自是多少. 12 16 12 12 16 24 16 20 答:C 依据下面条件进行计算:(核心知识点:结构体的对齐方式) 1. 结构体的大小等于结构体内最大成员大小的整数倍 2. 结构体内的成员的首地址相对于结构体首

面试题:面试题归类 !=!=未看

Java开发岗位面试题归类汇总,在微博看到的一篇文章,只有问题,没有答案,我具体写了一下每个问题大致的参考答案,仅供参考 一.Java基础 1.String类为什么是final的 答:主要是为了"效率" 和 "安全性" 的缘故.若 String允许被继承, 由于它的被使用率很高, 可能会降低程序的性能,所以String被定义成final.Final可以修饰类.方法.属性,分别代表类不可继承,方法不可重写,属性值不可改变.其中对于属性的修改,当final修饰基本数据类

面试题:面试题归类 !=!=未看 2

一.Java基础 1. String类为什么是final的. 答:主要是为了"效率" 和 "安全性" 的缘故.若 String允许被继承, 由于它的高度被使用率, 可能会降低程序的性能,所以String被定义成final. 2. HashMap的源码,实现原理,底层结构. 答:Java集合---HashMap源码剖析 3. 说说你知道的几个Java集合类:list.set.queue.map实现类咯... 4. 描述一下ArrayList和LinkedList各自实

go golang 笔试题 面试题 笔试 面试

发现go的笔试题目和面试题目还都是比较少的,于是乎就打算最近总结一下.虽然都不难,但是如果没有准备猛地遇到了还是挺容易踩坑的. 就是几个简单的笔试题目,也可能面试的时候直接给看让说结果.go面试题大本营 1, 用不同的goroutine去操作map的时候会存在线程同步的问题,把map换成int ,这个问题同样存在.在go里是这样. 2,下面这段代码输出的值为: func (){ jsonStr:=[]byte(`{"age":1}`) var value map[string]inte

Java面试题笔试题:

选择题(共50题,每题1.5分,共75分.多选题选不全或选错都不得分.)1. 以下属于面向对象的特征的是(C,D).(两项)A) 重载B) 重写C) 封装D) 继承 2. 以下代码运行输出是(C)public class Person{private String name="Person";int age=0;}public class Child extends Person{public String grade;public static void main(String[]

前端试题-CSS试题(1)

1. css属性命名区分大小写吗? 不区分,不过一般小写,便于理解 2. margin-top和margin-bottom对于行内(内敛inline)元素效果一样么? 3.padding-top和padding-bottom对于inline元素都会增加元素本身的大小么? 回答2,3,需要了解html里的替换元素和非替换元素. 替换元素是指作为其他内容点位符的一个元素.如img等.非替换元素是指内容包含在文档中的元素,例如span. 讨论margin-top和margin-bottom对行内元素是

PHP笔试题和面试题

1.不用新变量直接交换现有两个变量的值 (1)list($a,$b)=array($b,$a); (2)a=a+b,b=a-b,a=a-b 2.PHP数字金额转大小格式,同时说明思路 function daxie($num){ $da_num = array('零','一','二','三','四','五','六','七','八','九'); $return = ''; $len_num = strlen($num); if(!is_numeric($num) || $len_num < 0){