- 填写下述题目中的空白(10分)
1、若有定义int i = 1;,那么执行 (--i && i++ ); 语句后,i的值是 0 。
2、若有定义有: double x [5];,那么定义 指向此一维数组的指针的语句是 double*p=x; 。
若有定义有: char x [5][5];,那么定义 指向此二维数组的指针的语句是 char(* p)[5];p=x; 。
3、已知函数声明int getMax(int [][3],int);,那么使用变量名func,定义一个指向此函数的函数指针的语句为 int(*func)(int [][3],int);func=getMax; 。
4、对于语句int *pa[5];下列描述中正确的是( D )
A) pa是一个指向数组的指针,所指向的数组是5个int型元素
B) pa是一个指向某数组中第5个元素的指针,该元素是int型变量
C) pa [5]表示某个元素的第5个元素的值
D) pa是一个具有5个元素的指针数组,每个元素是一个int型指针
5、下面描述正确的是( D )。
A) int a = 0;和int b;,其中一条语句不是变量的定义
B) 位于代码块外的int a=0;和extern int b;,两条语句均为变量的定义。
C) int fun(char x[10], double *n);,此语句是函数的定义。
D) int fun(char x[10], double *n);和extern int b;,两条语句均是声明语句。
6、在函数调用时,当形参的数据类型为指针类型时,以下关于函数形参和实参的叙述中,正确的是( D )。
A)函数的实参和其对应的形参共占同一存储单元
B)形参只是形式上的存在,不占用具体存储单元
C)同名的实参和形参占同一存储单元
D)函数的形参和实参分别占用不同的存储单元
7、下面描述错误的是( D )
A) char * const p = 0; 不能修改指针变量p
B) const char *p = &a; 不能通过指针变量p修改变量a的值
C) char const * const p = 0;
不能修改指针变量p,且不能通过指针变量p修改变量a的值
D) const char * const p = 0;
不能修改指针变量p,且能通过指针变量p修改变量a的值
8、下述程序执行的结果是 FGH 。
#include <stdio.h>
void main() {
char w[][10] = { "ABCD", "EFGH", "IJKL", "MNOP" }, k = 0;
for (k = 1; k < 2; k++) printf("%s\n", &w[k][k]);}
9、在单链表中,指针P、C分别指向相邻的两个节点,删除C指针所指的结点,正确的操作是( A )。
A、P->next = C->next; C->next = 0; delete C; C=0;
B、C->next = P->next; C->next = C->next; delete C;C=0;
C、P->next = C; C = C->next; delete C; C=0;
D、P->next = P->next; C->next = 0; delete C;C=0;
10、软件设计中划分模块的一个准则是( B )。
A、低内聚低耦合 B、高内聚低耦合
C、低内聚高耦合 D、高内聚高耦合
- 以下为 Windows NT 下的 32 位 C++程序,请计算sizeof的值(10分)
char str[] = "编程";
int iArray[3][4] = { 0 };
void func(char cArray[3]) { };
void* ptr = malloc(10 * sizeof(int*));
//请计算
sizeof(str) = 5
sizeof(iArray) = 48
sizeof(cArray) = 4
sizeof(ptr) = 4
sizeof(iArray + 1) = 4
sizeof(iArray[0]) = 16
sizeof(iArray[0] + 1) = 4
- 简答题(20分)
1、预处理命令 #ifndef/#define/#endif 和 #pragma once的作用和区别
作用:二者都是可以避免同个文件被多次包含
区别:
- 移植性:#pragma once方式由编译器提供,保证同个文件(文件名相同)不会被包含多次,移植性差,不同编译器不一定支持,而#ifndef/#define/#endif方式是通过c++语言的宏定义避免文件被多次编译,在所有支持C++语言的编译器上都是可用的,移植性更高
- 性能:使用#ifndef/#define/#endif方式,编译器每次执行include指令都会读入该文件并解析代码;而#pragma once 方式,编译器不会重复打开文件,从而提高了了效率。
- 编码风格:#pragma once方式的代码整洁。避免了头文件的宏定义冲突以及#endif包含错误的情况
- 语意:#pragma once是针对文件的,告诉编译器,该文件只编译一次。而#ifndef/#define/#endif只是针对文件中的宏,防止三个指令间对宏进行重复定义,后者灵活性更强。
2、请说明,深拷贝和浅拷贝的概念和区别
浅拷贝:又叫位拷贝,当类的对象发生复制过程的时候,拷贝构造函数对类的成员变量采取按位复制,如:int型等。
深拷贝:如果一个类拥有资源,当这个类的对象发生复制过程的时候,拷贝构造函数对类的成员变量采取资源重新分配。
区别:
- 浅拷贝是默认拷贝构造函数,深拷贝构造函数需自定义。
- 类的成员变量中没有指针类型时,浅拷贝是可行的。 但当数据成员中有指针时,若采用浅拷贝,则两类中的指针类型的对象指向同一个地址,对象销毁时会出现delete野指针的错误;深拷贝则会在堆内存中另外申请空间来储存数据
3、请写出C++中构造函数的调用顺序,并分析其可能的缺点,针对缺点,尝试给出一种解决方案。
构造函数的调用次序:
- 调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左向右);
- 调用成员对象的构造函数,调用顺序按照它们在类中的声明的顺序;
- 派生类的构造函数
4、请给出对C++中this指针的理解
this指针的说明:this为C++关键字,它是一个指针,在任何一个类的函数成员运行过程中,指针this总指向当前调用者对象;一个对象的this指针属于对象this指针本身不可改,并且静态函数成员内部没有this指针,this作用域是在类内部。
this指针的使用:
- 当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数,如:void Func (int a, int b) { this->x +=a; this-> y+= b;}
- 在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this;
5、OOP三大特征封装性、继承性、多态性在C++中的实现方法和它们之间的联系。
封装性:封装可以隐藏实现细节, 使得代码模块化,体现在c++中的类的实现,提供外部接口,特定的访问权限以供操作类的成员
继承性:在类的基础上通过类的派生机制支持继承实现保持已有类的特性并构造新类。
多态性:通过虚函数实现一个接口多种方法的功能,程序在运行时才决定调用的函数。
C++支持两种多态性:(1)编译时多态性(静态多态,在编译时就可以确定对象使用的形式):通过重载函数实现;(2)运行时多态性(动态多态,其具体引用的对象在运行时才能确定):通过虚函数实现。
C++中,实现多态有以下方法:虚函数、抽象类、重载、覆盖、模板。
联系:封装可以使得代码模块化,继承可以扩展已存在的代码,它们的目的都是为了代码重用。而多态的目的则是为了接口重用
- 关于内存的思考题(20分)
1、程序:
#include <iostream>
void getMermory(char *p) {
p = (char*)malloc(100);
}
void main() {
char *str=NULL;
getMermory(str);
strcpy(str,"hello world");
printf(str);
}
运行上述程序,会有什么样的结果?
程序崩溃:
- 调用TestMemory(str)时str是值传递的,因此str依然是NULL,在运行到strcpy( str, "hello world" );处将产生错误。
-
形参p指向了一块新申请的空间,但是函数结束后p销毁了,但动态申请的内存并没有释放,造成内存泄漏。
2、程序
#include <iostream>
void getMermory(char **p,int num) {
*p = (char*)malloc(num);
}
void main() {
char *str=nulltpr;
getMermory(&str,100);
strcpy(str,"hello");
printf(str);
}
运行上述程序,会有什么样的结果?
程序结束后动态申请的内存并没有释放,造成内存泄漏;输出hello。
3、程序
#include <iostream>
typedef union {
long number;
int a[5];
char c;
} TEST1;
struct TEST2{
int count;
TEST1 tst;
double number;
}obj;
void main()
{
printf("%d\n", sizeof(TEST1)+sizeof(max));
}
运行上述程序,会有什么样的结果?
输出52
4、程序
#include <iostream>
#include <vector>
using namespace std;
void main() {
vector<int*> iPtrVec;
int *ptr1 = new int(10);
int *ptr2 = new int(10);
int *ptr3 = new int(10);
iPtrVec.push_back(ptr1);
iPtrVec.push_back(ptr2);
iPtrVec.push_back(ptr3);
for (vector<int*>::iterator itr = iPtrVec.begin();
itr != iPtrVec.end();
itr++)
{ iPtrVec.erase(itr);}
}
运行上述程序,会有什么样的结果?
程序崩溃;迭代器失效。
迭代器失效的原因:在容器中增加和删除元素
解决办法:重新赋一次值
纯手打 若有错 请指教!