C++测试一
简答题
-
说说C和C++的区别?(10分)
-
C++从范围上基本覆盖C语言,即C++是C语言的一个超集而C语言是C++的一个子集。
-
C语言是面向过程的编程语言,C++是面向对象的编程语言
-
C++支持运算符重载
-
C++支持友元函数
-
C++支持泛型编程
-
new/delete和malloc/free的区别?(10分)
- 从宏观功能上看,二者都是进行动态内存的申请和释放的,但是从性质上,二者的区别在于new/delete是C++中的关键字(不是函数),malloc/free是C语言中的函数。
-
从微观功能上看,new/new[]在使用时会调用类的构造函数,而malloc不会,delete/delete[]在使用时会调用类的析构函数,而free不会。
- 从返回值上看,new/new[]返回是对应类型的指针,而malloc则是返回的万能指针void*,使用时需要转换成对应类型的指针。
-
从异常机制上看,前者失败了会抛出bad_alloc,后者则是返回NULL
- 从申请所需的参数上看,new在意的是类型,而malloc在意的则是大小,当申请多个内存空间时,前者用的时new[],后者只需要给大小
-
从释放内存上看,前者new对应delete,new[]对应delete[];而后者一律用free
-
指针与引用的区别?(10分)
- 指针是实体变量,引用不是实体变量
-
指针可以不初始化,而引用则必须初始化
- 指针可以初始化为空,但引用不能
-
指针可以改变指向,引用则不能修改引用目标
- 可以定义指针的引用但是不能定义引用的指针
-
可以定义指针的指针,但是不能定义引用的引用
- 可以定义数组的引用,但是不能定义引用的数组
-
C++四种显示类型转换和使用场合(10分)
- 静态类型转换:原对象和目标类型在一个方向上可以进行隐式类型转换
- 去常属性类型转换:只适用于去除常指针或者常引用的常属性
- 重解释类型转换:不同类型的指针之间,或者整数与指针之间的类型转换
- 动态类型转换:只适用于有多态关系的父子指针或者引用类型之间的转换
-
什么是重载?C++是如何实现重载的?C语言如何调用C++实现的函数?(10分)
答:在一个类中,当函数名相同但参数不同时即构成重载;C++之所以能对同一作用域下的函数进行重载,是由于G++编译器在编译时,会对函数进行改名操作,形如_Zn函数名形参类型简写 _Z3maxii _Z3maxdd _Z3maxiii。如此参数列表不同的同名函数就构成了重载;
如果需要在C语言中调用C++的函数,那就必须使用extern "C"来编译C++的代码
-
什么是名字空间,名字空间有什么作用?(5分)
名字空间其实是对代码的逻辑划分,避免名字冲突
声明名字空间对当前作用域可见
-
什么是浅拷贝,什么是深拷贝?(5分)
对于一般的类型并没有深拷贝和浅拷贝的区别,仅针对指针进行区分。
浅拷贝仅拷贝内存地址,拷贝完成后两个指针指向同一片内存空间
深拷贝重新申请内存,将原本的内容拷贝到新申请的地址中,两个指针指向的内存空间不同但内容相同
-
什么是构造函数?什么是析构函数?什么是拷贝构造函数?什么是拷贝赋值函数?什么是移动构造函数,什么是移动赋值函数?这些函数分别在什么情况下会被调用?(20分)
构造函数:在一个类被创建时调用的函数,一般用于初始化类中成员变量或对其进行赋值
析构函数:在类类型变量消亡时调用的函数,一般是用于释放类类型中成员变量的内存
拷贝构造函数:通过一个存在的类给另一个类类型变量进行构造
移动构造函数:将一个存在的类中所有的成员和方法转移给另一个类类型变量,完成移动后原类类型变量消亡。
程序题
1.实现string类的单参构造、拷贝构造、拷贝赋值、析构函数(20分)
class String{
private:
char *s;
public:
String(const char *str = nullptr):s(strcpy(new char[str.s?strlen(str.s)+1]:1), str.s?str.s:""){}
~String(void){
if(s != nullptr){
delete [] s;
s = nullptr;
}
}
String(const String &str):s(strcpy(new char[str.s?strlen(str.s)+1:1], str.s?str.s:"")){}
String& operator = (const String& str){
if(this != &str){
String _tmp(str);
swap(s, _tmp.s);
}
return *this;
}
}