某狐畅游24校招-C++开发岗笔试
目录
本文题目源来自:[PTA程序设计类实验辅助教学平台](PTA | 程序设计类实验辅助教学平台)
一、单选题
1-1 若有说明 int a[2][3];
则对 a
数组元素的正确引用是
A. a[0][1+1]
B. a[1][3]
C. a[1,3]
D. a(1)(1)
1-2 下面有关重载函数的说法中正确的是
A. 重载函数名可以不同 B. 重载函数形参个数必须不同
C. 重载函数必须具有不同的返回值类型 D. 重载函数必须有不同的形参列表
1-3 对于该程序,以下说法正确的是
int CY=-1;
do{
CY=CY*CY;
}while(!CY);
A. 循环执行一次 B. 循环执行两次 C. 是死循环 D. 有语法错误
1-4 设数组定义为:
char XZ[ ]="ChangYou";
则数组 XZ
所占的空间为
A. 6 个字节 B. 7 个字节 C. 8 个字节 D. 9 个字节
1-5 定 a
是一个二维数组,则 a[i][j]
的指针访问方式为
A. *(a+i+j)
B. *(*(a+i)+j)
C. *(a+i)+j
D. *a+i+j
1-6
union MyUnion
{
int a;
short b;
};
int main()
{
MyUnion value;
value.a = 3;
printf("%d", value.b & 1);
}
在大端模式下输出结果是什么?
A. 3 B. 1 C. 2 D. 0
1-7
int main()
{
int a = 10;
int* b = &a;
*b = 0;
std::cout << a;
}
输出结果是
A. 0 B. 10 C. 不固定 D. 以上都不是
1-8
class A
{
public:
A() {
num++;
}
virtual void print() { std::cout << num; }
private:
int num = { 0 };
};
class B : public A
{
public:
virtual void print() { std::cout << num; }
private:
int num = { 0 };
};
int main()
{
A* a = new B();
a->print();
}
以上输出结果是什么
A. 0 B. 1 C. 3 D. 4
1-9
int main()
{
int i = 0;
int x = 0;
do {
if (i % 5 == 0)
{
std::cout << x;
x++;
}
++i;
} while (i < 10);
std::cout << x;
return 0;
}
输出结果是什么?
A. 01 B. 02 C. 012 D. 011
1-10
class A
{
public:
virtual void a() = 0;
A() {
std::cout << "A ";
}
};
class B : public A
{
public:
B() {
std::cout << "B ";
}
};
int main()
{
A* a = new B();
return 0;
}
输出结果是什么?
A. A B B. B A C. 编译错误 D. 以上都不是
1-11
class No
{
public:
virtual void printf() = 0;
private:
int* ptr;
};
int main()
{
int size = sizeof(No);
printf("%d", size);
}
在64位系统下输出结果是什么?
A. 1 B. 4 C. 8 D. 16
1-12 虚拟存储的基础是程序局部性理论,它的基本含义是
A. 代码的顺序执行
B. 程序执行时对内存访问的不均匀性
C. 变量的连续访问
D. 指令的局部性
1-13 有 m 个进程共享同一临界资源,若使用信号量机制实现对该临界资源的互斥访问,则信号量的变化范围是
A. 1 至 1−m
B. 1 至 m−1
C. 1 至 −m
D. 1 至 m
1-14 下列信息中,一般不属于进程控制块的信息是
A. 进程标识符
B. 进程状态
C. I/O 设备状态
D. 处理机状态
1-15 下面哪种内存管理方法有利于程序的动态链接?
A. 分段存储管理
B. 分页存储管理
C. 可变分区分配
D. 固定分区分配
1-16 某系统釆用 LRU 页置换算法和局部置换策略,若系统为进程 P 预分配了 4 个页框, 进程 P 访问页号的序列为 0, 1, 2, 7, 0, 5, 3, 5, 0, 2, 7, 6,则进程访问上述页的过程中,产生页置换的总次数是
A. 3
B. 4
C. 5
D. 6
1-17 执行()操作时,需要使用队列作为辅助存储空间。
A. 查找哈希表
B. 广度优先搜索图
C. 先序遍历二叉树
D. 深度优先搜索图
1-18 堆的形状是一棵
A. 完全二叉树
B. 满二叉树
C. 二叉排序树
D. 平衡二叉树
1-19 以下哪个数据结构底层是用红黑树实现的?
A. vector
B. list
C. map
D. deque
1-20 对包含 n 个元素的散列表进行检索,平均检索长度为
A. O (logn)
B. O (n)
C. O (n logn)
D. 不直接依赖于 n
1-21 排序过程中,对尚未确定最终位置的所有元素进行一遍处理称为一"趟"。下列序列中,不可能是快速排序第二趟结果的是
A. 5,2,16,12,28,60,32,72
B. 2,16,5,28,12,60,32,72
C. 2,12,16,5,28,32,72,60
D. 5,2,12,28,16,32,72,60
1-22 假定 T
是一个 C++ 类,下列语句执行之后,内存里创建了多少个 T
对象?
T b(5);
T c[6];
T &d = b;
T e=b;
T *p = new T (4);
A. 5
B. 8
C. 9
D. 12
1-23 假设字符串 char a[] = "abc123"
,char b[] = "xyz"
,那么使用字符串连接函数 strcat(a, b)
连接字符串 a
和 b
之后得到的结果是
A. abc123xyz
B. abc123
C. xyz
D. 内存溢出
1-24
enum string{
x1,
x2,
x3 = 10,
x4,
x5,
} x;
函数外部访问 x
等于什么?
A. 5 B. 12 C. 0 D. 随机值
1-25 关于以下代码,哪个说法是正确的?
myClass::foo(){
delete this;
}
..
void func(){
myClass *a = new myClass();
a->foo();
}
A. 它会引起栈溢出 B. 都不正确 C. 它不能编译 D. 它会引起段错误
1-26
struct T {
char a;
int *d;
int b;
int c:16;
double e;
};
T *p;
在 64 位系统以及 64 位编译器下,以下描述正确的是
A. sizeof§ == 24 B. sizeof(*p) == 24 C. sizeof(p->a) == 1 D. sizeof(p->e) == 4
二、单选题解析
1-1解析
A. a[0][1+1]
等价于 a[0][2]
。由于 a
是一个2行3列的数组,a[0][2]
是有效的,因为它访问的是第0行第2列的元素(数组索引从0开始)。
B. a[1][3]
试图访问第1行第3列的元素。但是,由于 a
是一个2行3列的数组,它的索引范围是 [0, 1]
对于行和 [0, 2]
对于列。因此,a[1][3]
是越界的,不正确。
C. a[1,3]
这种语法在C语言中是无效的。C语言不支持使用逗号 ,
来同时索引数组的两个维度。应该使用 a[1][3]
(尽管这个具体值越界了,但语法上应该使用方括号 []
)。
D. a(1)(1)
这种语法在C语言中也是无效的。C语言不支持使用圆括号 ()
来索引数组。应该使用方括号 []
。
正确答案:A
1-2解析
A. 重载函数名可以不同:不正确。函数重载的定义就是函数名相同但参数列表不同。如果函数名不同,那就是不同的函数,而不是重载。
B. 重载函数形参个数必须不同:不正确。虽然形参个数不同是一种重载方式,但重载还可以通过参数类型不同或参数顺序不同来实现。只要参数列表(包括参数类型和数量)不同,就可以构成重载。
C. 重载函数必须具有不同的返回值类型:函数重载与返回值类型无关。即使两个函数的返回值类型不同,如果它们的参数列表相同,也不能构成重载。
D. 重载函数必须有不同的形参列表:这是正确的。函数重载的关键在于参数列表的不同,可以是参数的数量不同,也可以是参数的类型不同,或者参数的顺序不同(对于某些特定的类型,如用户自定义类型)。只要参数列表不同,就可以构成重载。
正确答案:D
1-3解析
初始化变量 CY
为 -1
。进入do-while循环体,首先计算CY = CY * CY。第一次计算时,CY = -1 * -1 = 1
。循环结束后,检查while条件!CY。
在第一次循环后,CY
的值为 1
,所以 !CY
(即 !1
)为 false
(因为 1
是非零值,在C/C++中,非零值表示真,而零表示假,但 !
操作符会将其反转)。由于 while
条件为 false
,循环将不会再次执行。
正确答案:A
1-4解析
在C语言中,字符串是以字符数组的形式存储的,且字符串的末尾会自动添加一个空字符 \0
作为结束标志。这个空字符也是数组的一部分,会占用存储空间。
因此,数组 XZ
的总长度为:8个字符('C', 'h', 'a', 'n', 'g', 'Y', 'o', 'u') + 1个字符(\0
) = 9个字符
每个字符占用1个字节,所以数组 XZ
所占的空间为9个字节。
正确答案:D
1-5解析
A. *(a+i+j)
: a+i+j
试图将行索引和列索引相加,然后将其用作一个单一的指针偏移量,这并不符合二维数组的访问方式。
B. *(*(a+i)+j)
:正确的。a+i
是指向第 i
行的指针,*(a+i)
是第 i
行数组本身,*(a+i)+j
是指向第 i
行第 j
列元素的指针,最后 *(*(a+i)+j)
得到这个元素的值。
C. *(a+i)+j
: *(a+i)+j
是一个指针加上一个整数,结果仍然是一个指针,而不是元素的值。要得到值,你需要对结果再进行一次解引用(即 *(*(a+i)+j)
)。
D. *a+i+j
: *a
是第一行的第一个元素的值,而不是一个指针。然后 *a+i+j
试图将这个值(一个整数或字符等)与行索引和列索引相加,这是不合法的操作。
正确答案:B
1-6解析
大端模式(Big-Endian):在这种字节序中,数据的最高有效字节(MSB)存储在最低的内存地址,而最低有效字节(LSB)存储在最高的内存地址。
联合体(Union):在C/C++中,联合体是一种特殊的数据结构,它允许在相同的内存位置以不同的类型来存储数据。但是,一次只能存储联合中定义的某一个成员的值,因为所有成员共享同一块内存。
value.a = 3;
:将整数3赋值给value.a
。在大端模式下,整数3(假设为32位)在内存中的表示可能是00 00 00 03
(十六进制)。
value.b
:由于value.a
和value.b
共享同一块内存,当访问value.b
时,我们实际上是在查看value.a
的前两个字节(或更少,取决于short
的大小)。在大端模式下,这两个字节是00 00
。
如果short
是16位,那么value.b
的值将是这两个字节组成的数,即0x0000
,转换为十进制是0。
value.b & 1
:这是计算value.b
与1的按位与操作。由于value.b
的值为0,0 & 1
的结果也是0。
因此,无论short
是16位还是更大的位数(只要不超过int
的前几个字节),在大端模式下,value.b
的值都将是由value.a
的前几个字节决定的,而这些字节在value.a
被赋值为3时都是0。
正确答案:D
1-7解析
在这个程序中,a
是一个整型变量,其初始值为 10。b
是一个指向整型的指针,它被初始化为指向 a
的地址(即 &a
)。
接下来,通过解引用指针 b
(即 *b
),将 a
的值修改为 0。
因此,当执行 std::cout << a;
时,a
的值已经是 0,所以输出结果是 0。
正确答案:A
1-8解析
类 A
和类 B
都各自有一个名为 num
的私有成员变量。这意味着每个类实例都会有自己的 num
变量,并且它们之间不会相互影响。
在类 A
的构造函数中,num
(类 A
的 num
)被递增。但是,这个递增只影响类 A
实例的 num
变量,对类 B
的 num
变量没有影响。
当创建 B
类的实例时(通过 new B()
),首先会调用基类 A
的构造函数。在 A
的构造函数中,A
的 num
成员被递增到 1(假设没有其他 A
类的实例被创建)。然而,当调用 B
类的 print
方法时,它打印的是 B
类的 num
成员,该成员在 B
的构造函数中被初始化为 0。
因此,代码的输出将是: 0,因为 a->print()
实际上调用的是 B
类的 print
方法,它打印的是 B
类的 num
成员,该成员的值是 0。
正确答案:A
1-9解析
初始化 i
为 0,x
为 0。
进入 do-while
循环,该循环至少执行一次。
在循环中:
- 当
i = 0
时,i % 5 == 0
成立,输出x
(此时为 0),然后x
自增变为 1,i
自增变为 1。 - 当
i = 1, 2, 3, 4
时,i % 5 != 0
,不执行输出和x
的自增,只执行i
的自增。 - 当
i = 5
时,i % 5 == 0
成立,输出x
(此时为 1),然后x
自增变为 2,i
自增变为 6。 - 当
i = 6, 7, 8, 9
时,同样i % 5 != 0
,只执行i
的自增。
循环结束后,i
达到 10,退出循环。再输出 x
的当前值2。
正确答案:C
1-10解析
类A
包含了纯虚函数void a() = 0;
,只要类中有纯虚函数,那么这个类就是抽象类。抽象类是不能直接用来创建对象实例的,不过可以定义指向抽象类的指针或者引用,用于实现多态性相关的操作。
类B
继承自类A
,但是类B
并没有对从类A
继承过来的纯虚函数a()
进行重写实现。所以类B
也依然是抽象类,虽然在main
函数中有A* a = new B();
这样的语句,试图通过基类指针去创建派生类B
的对象,但由于B
仍然是抽象类,按照 C++ 语法规则,抽象类是不允许被实例化的,因此在编译阶段就会报错,无法得到具体的输出结果。
正确答案:C
1-11解析
在 C++ 中,虽然No
类是一个抽象类(因为它包含了纯虚函数virtual void printf() = 0;
),但是编译器依然会为其生成一个虚函数表指针(在 64 位系统下,这个指针的大小通常是 8 字节,用于指向类的虚函数表,虚函数表中存放着该类的虚函数的地址等相关信息)。
No
类中还包含了一个int*
类型的私有成员变量ptr
,在 64 位系统中,指针类型的大小也是 8 字节。
类对象的大小计算遵循一定规则,一般来说要考虑成员变量以及编译器为实现多态等机制添加的相关内容(比如虚函数表指针)。对于No
类,其大小主要由虚函数表指针和int*
类型的成员变量这两部分组成,在 64 位系统下,虚函数表指针占 8 字节,int*
成员变量占 8 字节,总共就是 8 + 8 = 16 字节。
正确答案:D
1-12解析
A. 代码的顺序执行:虽然程序的顺序执行是计算机运行的基础,但它并不直接描述程序对内存访问的不均匀性,即局部性原理。因此,A选项不是最佳答案。
B. 程序执行时对内存访问的不均匀性:这恰好描述了程序局部性理论的核心。程序在执行时,往往会不均匀地访问内存,即某些存储区域被频繁访问,而另一些则较少被访问。这种不均匀性构成了程序局部性理论的基础,包括时间局部性和空间局部性。因此,B选项是正确答案。
C. 变量的连续访问:虽然变量的连续访问可能表现出一定的局部性,但它并不全面描述程序局部性理论。程序局部性理论更多地关注程序执行过程中对整个内存访问模式的不均匀性。因此,C选项不是最佳答案。
D. 指令的局部性:指令的局部性虽然在一定程度上反映了程序执行的特点,但它更多地关注指令本身而不是内存访问。程序局部性理论主要关注的是内存访问的不均匀性。因此,D选项也不是最佳答案。
正确答案:B
1-13解析
临界资源应互斥使用,互斥信号量m的初值为1。当没有进程使用临界资源时,m值为1;有一个进程使用临界资源且无进程等待使用该资源时,m值为0;有一个进程使用临界资源且有一个进程等待使用该资源时,m值为 -1;依此类推,最多可能有m -1个进程等待使用该临界资源。对应信号量的值就是-(m-1)=1-m。
正确答案:A
1-14解析
A. 进程标识符:进程标识符是PCB中的关键信息之一,用于唯一地标识一个进程。它使得操作系统能够区分和管理不同的进程。因此,A选项是进程控制块的信息。
B. 进程状态:进程状态也是PCB中的重要信息,它描述了进程的当前状态(如就绪、运行、阻塞等)。操作系统根据进程状态来调度和管理进程。因此,B选项是进程控制块的信息。
C. I/O 设备状态:I/O设备状态通常描述的是与进程相关的输入/输出设备的状态,如设备是否忙碌、是否有I/O请求等待处理等。这些信息虽然与进程的执行有关,但它们并不直接存储在进程控制块中。相反,它们通常被保存在与I/O系统相关的数据结构中,或者由设备驱动程序进行管理。因此,C选项一般不属于进程控制块的信息。
D. 处理机状态:处理机状态信息包括处理器的各种寄存器中的内容,如通用寄存器、控制寄存器(如PSW寄存器)等。这些信息在进程切换时需要被保存和恢复,因此它们被存储在进程控制块中。所以,D选项是进程控制块的信息。
正确答案:C
1-15解析
A. 分段存储管理:分段存储管理允许程序被划分为不同的逻辑段,每个段对应程序中的一个逻辑单元(如主程序、子程序、数据等)。这种方式使得程序的逻辑结构更加清晰,易于组织和维护。更重要的是,分段存储管理支持动态链接,因为每个段都有自己的基址和界限,可以根据需要独立增长或缩小,从而适应动态链接时程序模块的变化。
B. 分页存储管理:分页存储管理将内存分为一系列固定大小的分区(页框或页帧),并将进程的信息存储在这些页框中。虽然分页存储管理也支持动态存储分配,但它更侧重于提供均匀划分的地址空间和内存保护,而不是直接支持程序的动态链接。分页存储管理主要通过页表来实现逻辑地址到物理地址的映射。
C. 可变分区分配:可变分区分配(又称动态分区分配)不预先划分内存,而是在程序装入内存时,根据进程的大小动态地建立分区。虽然这种方式提供了灵活性,但它本身并不直接支持程序的动态链接。动态分区分配主要关注的是如何有效地管理和利用内存空间。
D. 固定分区分配:固定分区分配将内存划分为大小相等或不等的固定分区,每个应用进程占用一个分区。这种方式缺乏灵活性,因为分区的大小是固定的,难以适应动态链接时程序模块的变化。
正确答案:A
1-16解析
系统采用 LRU 页置换算法:LRU(Least Recently Used)算法是一种常用的页面置换算法,它会选择最近最少使用的页面进行置换。
局部置换策略:这意味着页面置换只会在分配给进程的页框内进行,不会影响到其他进程的页框。
题中所问的是页置换次数,而不是缺页次数,即前四次缺页未换页的情况不计入在内,即产生页置换的总次数是为5次(缺页产生总次数为9次)
正确答案:C
1-17解析
查找哈希表:哈希表通过哈希函数将关键字映射到表中的某个位置,查找时直接根据哈希值定位,不需要辅助存储结构。因此,A选项不符合题意。
广度优先搜索图(BFS):BFS是一种遍历或搜索算法,它从根节点开始,首先访问所有相邻的节点,然后对于每一个已经访问过的相邻节点,再依次访问它们的相邻节点(已访问过的节点不再重复访问)。这个过程需要使用队列来存储待访问的节点,以保证按层次顺序访问。因此,B选项符合题意。
先序遍历二叉树:先序遍历是一种深度优先的遍历方式,它按照"根节点-左子树-右子树"的顺序进行遍历。这种遍历方式不需要使用队列,而是通常使用栈或递归来实现。因此,C选项不符合题意。
深度优先搜索图(DFS):DFS也是一种遍历或搜索算法,它沿着图的每一条分支尽可能深地搜索,直到达到叶节点或图的尽头,然后回溯并继续搜索其他未探索的分支。DFS通常使用栈或递归来实现,而不是队列。因此,D选项不符合题意。
正确答案:B
1-18解析
堆的定义:堆是一种特殊的完全二叉树。在堆中,每个节点的值都大于或等于(最大堆)或小于或等于(最小堆)其子节点的值。
完全二叉树:除了最后一层外,每一层都是满的,且最后一层的节点都靠左对齐。
满二叉树:除了叶子节点外,每个节点都有两个子节点。
二叉排序树(BST):左子树节点的值小于根节点的值,右子树节点的值大于根节点的值。
平衡二叉树:任何节点的两个子树的高度差不超过1。
正确答案:A
1-19解析
vector是C++ STL中的一个序列容器,它底层实现为动态数组。这意味着它会根据需要动态地调整其大小,并在内部使用连续的内存块来存储元素。因此,vector的底层并不是红黑树。
list同样是C++ STL中的一个序列容器,但它底层实现为双向链表。链表中的每个元素都包含数据部分和指向其前驱和后继元素的指针。这种结构使得list在插入和删除操作上具有高效性,但底层并不是红黑树。
map是C++ STL中的一个关联容器,它存储键值对,并根据键来排序和快速查找值。在C++ STL中,map的底层通常实现为红黑树。红黑树是一种自平衡的二叉查找树,它能在O(log n)的时间复杂度内完成插入、删除和查找操作。因此,map的底层是用红黑树实现的。
deque是C++ STL中的一个双端队列容器,它允许在两端进行高效的插入和删除操作。deque的底层实现通常为一个动态数组加上一些额外的指针,用于支持两端的操作。因此,deque的底层并不是红黑树。
正确答案:C
1-20解析
对于包含n个元素的散列表(哈希表)进行检索时,其平均检索长度(也称为平均查找时间或平均访问时间)并不直接依赖于n,而是受到散列函数的质量、散列表的大小(容量)、负载因子(即表中元素数量与表容量的比值)以及冲突解决策略等因素的影响。
负载因子:表中已占用位置数与总位置数的比值。负载因子越大,冲突的可能性越大,平均检索长度也越长。
散列函数:散列函数的分布特性影响关键字的映射情况。一个好的散列函数能够减少冲突,从而降低平均检索长度。
解决冲突的方法:如开放地址法、链地址法等。不同的方法会影响平均检索长度。
正确答案:D
1-21解析
快速排序是基于分治思想的一种排序算法,它首先会选择一个基准元素(Pivot),通过一趟排序将待排序序列划分为两部分,左边部分的元素都小于等于基准元素,右边部分的元素都大于等于基准元素。然后对划分后的左右两部分分别递归地进行排序,直到整个序列有序。
A选项(5,2,16,12,28,60,32,72):第一趟可以72为基准元素,第二趟以28为基准;
B选项(2,16,5,28,12,60,32,72):第一趟可以72为基准元素,第二趟以2为基准;
C选项(2,12,16,5,28,32,72,60):第一趟可以28为基准元素,第二趟以2为基准;
D选项(5,2,12,28,16,32,72,60):第一趟可以12为基准元素,第二趟没有可满足的;
正确答案:D
快速排序具体实现可参考视频:三分钟学会快速排序_哔哩哔哩_bilibili
1-22解析
T b(5);这行代码创建了 1
个 T 类型的对象 b,并用 5初始化它。
T c[6];这行代码创建了一个包含 6
个 T 类型对象的数组 c。
T &d = b;这行代码创建了一个对 b 的引用 d。它并没有创建新的 T 对象,只是为 b 提供了一个别名。
T e = b;这行代码创建了1
个新的 T 类型的对象 e,并用 b 初始化它。
T *p = new T(4);这行代码在堆上创建了1
个新的 T类型的对象,并用 4 初始化它。p 是一个指向这个新对象的指针。
正确答案:C
1-23解析
char a[] = "abc123";
char b[] = "xyz";
字符串 a 初始化为 "abc123",这意味着 a 数组在内存中占用了足够的空间来存储这 6 个字符加上一个空字符(\0),总共 7 个字符的空间。字符串 b 则初始化为 "xyz",同样地,它占用了 4 个字符的空间(3 个字符加上一个空字符)。
当执行 strcat(a, b) 时,strcat 会将 b 中的字符(包括终止的空字符之前的所有字符)追加到 a 的末尾,并覆盖 a 字符串末尾的空字符。这意味着 a 需要有足够的空间来存储连接后的字符串及其终止的空字符。
在这个例子中,a 的原始空间只够存储 7 个字符。当执行 strcat(a, b) 后,a 需要存储 "abc123xyz",这是 8 个字符(包括终止的空字符)。由于 a 的空间不足以存储这 8 个字符,因此会导致缓冲区溢出,即内存溢出。
正确答案:D
1-24解析
定义在函数外是全局变量,程序初始化为0;若是定义在函数内,编译器提示变量未初始化错误。
此时x1=0,x2=1,x3=10,x4=11,x5=12。
正确答案:C
1-25解析
delete this;
是一种合法的操作,在C++中允许对象通过其成员函数删除自身。这通常用于管理对象生命周期的高级模式,比如在某些单例模式或资源管理类中。在
func
函数中,首先通过new
操作符创建了一个myClass
类型的对象,并将该对象的指针赋值给a
。然后通过
a->foo();
调用了myClass
的成员函数foo
,在foo
中执行了delete this;
。内存管理和指针状态:当
delete this;
执行后,a
指向的内存已被释放。但重要的是,指针a
本身并没有被设置为nullptr
或以其他方式标记为无效。因此,a
仍然持有一个悬空指针(dangling pointer),指向已经被释放的内存。
A. 它会引起栈溢出:栈溢出通常发生在递归调用过深或局部变量过多时。这里不涉及递归调用,也没有过多的局部变量,因此不会引起栈溢出。
B. 都不正确:其他三项都不正确故选B
C. 它不能编译:代码语法正确,没有编译错误。
D. 它会引起段错:段错误(segmentation fault)通常发生在访问无效内存时。在这个例子中,delete this;
后,a
指向的内存被释放,但 a
指针本身未被置空。如果接下来通过 a
访问已被释放的内存(尽管示例代码中没有这样的操作),则可能会引起段错误。然而,仅凭这段代码本身,并没有直接的段错误发生,因为 a
指针在 delete this;
后未被使用。
正确答案:B
1-26解析
指针大小:在 64 位系统中,指针的大小通常是 8 字节(64 位)。
基本数据类型大小:
char
通常是 1 字节,int
通常是 4 字节(32 位),double
通常是 8 字节(64 位)。结构体内存对齐:编译器可能会插入填充字节以满足对齐要求,以提高访问速度。
A. sizeof(p) == 24
:错误。p
是一个指向 T
的指针,在 64 位系统中,指针大小为 8 字节。
B. sizeof(*p) == 24
:错误。*p
是 T
类型的一个实例。如前所述,T
的大小可能因填充字节而大于 24 字节。
C. sizeof(p->a) == 1
:正确。p->a
是 char
类型,其大小是 1 字节。
D. sizeof(p->e) == 4
:错误。p->e
是 double
类型,其大小是 8 字节。
正确答案:C