1 C++ class和struct的区别
C++中的strutct对C中的struct进行了扩充,它已经不再是一个包含不同数据类型的数据结构,已经获取了太多的功能。
struct中能包含成员函数吗?能!
struct能继承吗?能!!
struct能实现多态吗?能!!!
那么区别何在?
一、最本质的区别就是默认的访问控制,体现在两方面:
(1)默认的继承访问权限。struct是public的,class是private的。
(2)struct作为数据结构的实现体,它默认的数据访问控制是public的,而class作为对象的实现体,它默认的成员变量访问
控制是private的。
二、“class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。
参考资料:
http://blog.sina.com.cn/s/blog_48f587a80100k630.html
2 C++中用new和不用new创建对象区别
1 作用域不同
不用new:作用域限制在定义类对象的方法中,当方法结束时,类对象也被系统释放了(安全不会造成内存系统泄露)
用new:创建的是指向类对象的指针,作用域变成了全局,当程序结束时,必须用delete删除,系统不会自动释放
(不注意可能造成内存泄露)
2 一个类对象,一个是指向类对象的指针
1.c++中
1. 声明只是表示一个对象的引用,比如我们的语句:
MyClasee myclass;
这里是一个空引用,而通过new关键字可以实例化一个MyClasee的实例,
所以语句:
myclass = new MyClass();
2.栈,放的是局部变量,他的生存期就是他所处的语句块(也就是离他最近的一对{}),离开了他的生存期他就失效了,一般声明形式就是在栈中定义的。堆上的空间需要你用new申请,用delete或者delete[]归还,在进程的范围内,该内存的生存期就完全由你操作了;
3.C++里的new负责的是内存的分配,并不负责把实例初始化成有效状态。而C#则两步都要做。所以我们经 常在C++里new一个对象或者用指针操作对象的时候,要先清零或者设置null,但是在C#里一般不用这么做,因为它已经做了这一步。
-----------------------------------------------------------------------------
(1)CFont myFont;//定义了myFont变量,然后就可以直接用myFont变量了
(2)CFont myFont = new CFont();//myFont也可以直接使用了
这两个有什么区别吗?
空间分配的位置不一样
第一个系统管理内存
第二个需要自己管理释放
直接创建是编译器就留出了空间,在程序装入的数据段里
用new创建的空间是运行期在堆空间分配,用完后要自己记得归还(delete)
2.Java中
使用new来创建,那么程序就会在heap上分配空间来储存它,但是当你引用的时候则不然,你可以为它分配空间也可不分配,看你需要了!分配了就是个对象,如果不分配就是null,不占用任何硬件资源。
3 对于一个频繁使用的短小函数,在C语言中用宏实现,在C++中应用什么实现?
A 虚函数
B 内联函数
C 友元
D 抽象类
正确答案:B
参考解析:
虚函数:用virtual关键字申明的函数叫做虚函数,虚函数是用来实现多态的,多态用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。
内联函数:内联函数的编译代码与其他程序代码“内联”起来了。也就是说,编译器将使用相应的函数代码替换函数调用。对于内联代码,程序无需跳到另一个位置处执行代码,再跳回来,因此,内联函数的运行速度比常规函数稍快,但代价是占用更多内存。
要使用这项特性,必须采取下述措施之一:
(1)在函数声明前加上关键字inline
(2)在函数定义前加上关键字inline
友元:实际上具体大概有下面两种情况需要使用友元函数:(1)运算符重载的某些场合需要使用友元。(2)两个类要共享数据的时候。
抽象类:
4 C++类体系中,不能被派生类继承的有?
A 构造函数
B 静态成员函数
C 非静态成员函数
D 赋值操作函数
正确答案:AD
5 std::vector::iterator重载了下面哪些运算符?
A ++
B >>
C *(前置)
D ==
正确答案:ACD
6 下列关于C语言中指针的说法错误的是:___
A 指针的值是一个地址
B 非法指针是指该指针的值不是一个已经分配的内存地址
C 两个指向同类型地址的指针之间做减法一般是没有意义的
D 指针的指针占用的内存空间和其他指针占用的内存空间相同
正确答案:B
非法指针并不只是未分配的内存,而包括所有已经不能访问的内存,例如,指向已经返回的函数局部变量,越过数组边界的地址等。
7 下面关于typedef char *String_t; 和#define String_d char * 这两句在使用上的区别描述错误的是?
A typedef char *String_t 定义了一个新的类型别名,有类型检查
B #define String_d char * 只是做了个简单的替换,无类型检查
C 前者在预编译的时候处理,后者在编译的时候处理
D 同时定义多个变量的时候有区别,主要区别在于这种使用方式String_t a,b; String_d c,d; a,b ,c 都是char*类型,而d 为char 类型
正确答案: C
参考解析:
答:typedef char *String_t 定义了一个新的类型别名,有类型检查。而#define String_d char * 只是做了
个简单的替换,无类型检查,前者在编译的时候处理,后者在预编译的时候处理。
同时定义多个变量的时候有区别,主要区别在于这种使用方式String_t a,b; String_d c,d; a,b ,c 都是
char*类型,而d 为char 类型
由于typedef 还要做类型检查。。#define 没有。。所以typedef 比#define 安全。
8 函数x的定义如下,问x(x(8))需要调用几次函数x(int n)?
int x(int n){
cnt++;
if(n<=3)
{
return1;
}
else
{
returnx(n-2)+x(n-4)+1;
}
}
A 16
B 18
C 20
D 22
正确答案:B
参考解析:
9 print()函数是一个类的常成员函数,它无返回值,下列表示中正确的是()
A const void print();
B void const print();
C void print() const;
D void print(const);
正确答案:C
参考解析:
const void print(const int num)const 第一个const修饰返回类型 第二个const修饰参数 第三个const修饰调用对象
10 下面重载乘法运算符的函数原型声明中正确的是:
A MyClass operator *(double ,MyClass);
B MyClass operator *(MyClass ,MyClass);
C MyClass operator *(double ,double);
D MyClass operator *(MyClass ,double);
11 以下程序的输出结果是:
#define M(x,y,z) x*y+z
main()
{
int a=1, b=2, c=3;
printf("%d\n",M(a+b,b+c,c+a));
}
A 19
B 17
C 15
D 12
正确答案:D
参考解析:
#define M(x,y,z) x*y+z
M(a+b,b+c,c+a)
宏展开 a+b*b+c+c+a = 12
如果这样声明 #define M(x,y,z) (x)*(y)+z
宏展开 (a+b)*(b+c)+ c + a = 19
就变成我们想要的结果了
所以宏定义时候 参数别忘记加括号
12 下列关于C/C++的宏定义的说法中,不正确的是:
A 宏定义的常量更容易理解,如果可以使用宏定义常量的话,要避免使用 const常量
B 宏的嵌套定义过多会影响程序的可读性,而且很容易出错
C 相对于函数调用,宏定义可以提高程序的运行效率
D 宏定义不检查参数正确性,会有安全隐患
正确答案: A
参考解析:
宏定义由预编译器来处理,当你定义一个记号#define RATIO 1.652时,RATIO可能从未被编译器看到,而直接被预处理其移走了,如果你的定义是#define RATIO ,在预处理进行一个宏替换的时候,由于你调用地方的特殊性,你会获得一个莫名奇妙的错误,但是如果你使用的const double RATIO = 1.652,当你没有初始化这个变量,则在这个变量出错地方编译器将给出错误信息,可以方便程序设计者很快的找出错误所在。这就是在effective C++中作者所说的尽量以const enum inline 替换define 条款。
13 关于函数模板,描述错误的是?
A 函数模板必须由程序员实例化为可执行的函数模板
B 函数模板的实例化由编译器实现
C 一个类定义中,只要有一个函数模板,则这个类是类模板
D 类模板的成员函数都是函数模板,类模板实例化后,成员函数也随之实例化
正确答案:A
参考解析
正确的说法是函数模板必须由编译器根据程序员的调用类型实例化为可执行的函数。
14 下面程序段包含4个函数,其中具有隐含this指针的是()
int f1();
class T
{
public:static int f2();
private:friend int f3();
protect:int f4();
};
正确答案: D
参考解析:
struct{
char a;
int b;
char c;
}
A 8
B 4
C 6
D 2
参考解析:
- 数据成员自对齐,即数据成员起始地址为数据类型长度的整数倍,如该题int型b只能从0,2,4...等地址处开始放;
- 结构体总长度是结构体中有效对齐值的整数倍,有效对齐值,如该题没明确指出,则为最长数据成员(int b)长度的整数倍;
16 “引用”与指针的区别是什么?
A 指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
B 引用通过某个引用变量指向一个对象后,对它所指向的变量间接操作。程序中使用引用,程序的可读性差;而指针本身就是目标变量的别名,对指针的操作就是对目标变量的操作。
C 指针比引用更节省存储空间
D 以上都不正确
正确答案: A
参考解析
引用是变量的别名,指针值变量的地址,通过改变所指向的地址的值来改变变量的值,属于间接操作。所以A正确B错误
引用是别名,不占内存空间,指针的变量的地址,存储指针要占一定的内存空间,所以引用更节省内存空间
17 一个C语言程序在一台32位机器上运行。程序中定义了三个变量xyz,其中x和z是int型,y为short型。当x=127,y=-9时,执行赋值语句z=x+y后,xyz的值分别是
A x=0000007FH,y=FFF9H,z=00000076H
B x=0000007FH,y=FFF9H,z=FFFF0076H
C x=0000007FH,y=FFF7H,z=FFFF0076H
D x=0000007FH,y=FFF7H,z=00000076H
正确答案: D
参考解析
机器里存放的是补码,C语言中变量以补码形式存放在内存中,正数的补码与原码相同,负数求补码方式为(符号位不变,其余各位取反,最后末尾加1);
32位机器:int 32位,short 16位。
x = 127,正数,原码:0111 1111,补码:0111 1111,扩展到32位高位补0,结果为0000007FH;
Y = -9,负数,原码:1000 1001,补码:1111 0111,扩展到16位高位补1,结果为FFF7H;
z = x + y = 118,原码:0111 0110,补码:0111 0110,扩展到32位高位补0,结果为00000076H。
注意:扩展时,符号位不变。
18 以下程序打印的两个字符分别是()
typedef struct object object
struct object
{
char data[3];
};
int main(void)
{
object obj_array[3]={{'a','b','c'},
{'d','e','f'},
{'g','h','i'}};
object*cur=obj_array;
printf("%c %c\n",*(char*)((char *)(cur)+2),*(char*)(cur+2));
return 0
}
A c g
B b d
C g g
D g c
正确答案: A
参考解析
cur本为object类型指针 第一个占位符输出时,参数中将cur先强制转化为字符型指针 然后加2,即指向obj_array数组的第一个元素中的字符c,而第二个占位符输出时,参数中先让cur指针加2,即到达obj_array第3个元素的地址处,然后强制转化为字符型指针,再用*获取1个字节的内容即字符g
19 C++中关于堆和栈的说法,哪个是错误的:
A 堆的大小仅受操作系统的限制,栈的大小一般一般较小
B 在堆上频繁的调用new/delete容易产生内存碎片,栈没有这个问题
C 堆和栈都可以静态分配
D 堆和栈都可以动态分配
正确答案: C
参考解析
选C,静态分配是指在编译阶段就能确定大小,由编译器进行分配,堆不可以进行静态分配,堆的申请都是在执行过程中进行的。
A,堆和栈的大小都可以设置,栈一般只有几KB。
B,堆在动态分配时,要申请连续的内存空间,释放后会产生碎片。
D,堆是使用malloc()、calloc()、realloc()等函数动态分配的,而使用alloca()函数可以动态分配栈的内存空间,释放的时候由编译器自己释放。
Reference:
http://www.cnblogs.com/BeyondAnyTime/archive/2012/06/04/2535305.html