GESP 六级 · GESP 202309 C++ 六级 第 7 题

选择题 · 答案 D · 考点:类与对象、指针与内存

← 整套速查表 GESP 六级 全部真题

题目

有关下面 C++ 代码的说法,正确的是( )。

#include <iostream>
using namespace std;

class ManyData {
    int * __data;
    int head, tail, capacity;
public:
    ManyData(int cap) {
        capacity = cap;
        __data = new int[capacity];
        head = tail = 0;
    }
    void push(int val) {
        __data[tail++] = val;
    }
    int pop() {
        return __data[--tail];
    }
    int size() {
        return tail - head;
    }
};

int main() {
    auto myData = ManyData(100);
    myData.push(1);
    myData.push(2);
    myData.push(3);
    myData.push(100);
    cout << myData.size() << endl;
    cout << myData.pop() << endl;
    return 0;
}
答案:D

考点

类与对象指针与内存

解题思维

拿到题先别急着看选项,把代码过一遍:构造函数里new了数组,push只往tail端加,pop只从tail端减。这种一端进一端出的操作模式,就是典型的栈(Stack)行为。选项里说队列的,直接排除;说访问私有成员的,肯定报错。剩下的就是看边界条件(满、空)会不会越界,这时候D项的异常处理提示就顺理成章了。

常见错误

很多学生看到tail++和--tail就以为是队列,因为觉得‘先进先出’,其实这是栈的‘后进先出’;还有人觉得new出来的指针没初始化就会报错,忽略了构造函数里已经new了;最容易被C项坑到,以为__data前面加了两个下划线就是内部变量,其实C++里私有成员外部完全不可见,直接访问会编译不通过;还有人觉得push/pop永远不会越界,忘了容量只有100,push了101次就爆内存了。

详细解析(节选)

【考点定位】本题核心考查C++类的封装机制(私有成员访问权限)、栈(Stack)与队列(Queue)的操作特征区别,以及动态数组边界溢出时的异常安全问题。GESP六级大纲明确要求掌握成员变量访问权限与异常安全编程,命题人故意用私有指针和单向操作卡住大量考生对封装边界的模糊认知,以及忽略边界检查的侥幸心理。

【代码逐行拆解】 先过一遍构造函数:ManyData(int cap)里,capacity被赋初值,然后new了一个长度为cap的整型数组赋给__data,最后tail和head都初始化为0。注意这里__data是私有成员(前面两个下划线),外部代码完全无法直接读写,只能调用成员函数。 再看push(int val):它只做了__data[tail++] = val;没有检查tail是否已经等于capacity。这意味着如果连续push超过capacity次,就会发生数组越界写入,这是典型的运行时错误(segmentation fault)。 接着看pop():返回__data[--tail];同样没有检查tail是否已经为0。如果此时栈空,tail是0,--tail会让它变成-1,访问__data[-1]就是读内存之外的位置,也是严重的运行时错误。 size()返回tail-head,这里head一直是0,所以size就是tail,逻辑上没问题。

【选项逐一分析】 A项说“不能正常运行”。这不对。main函数里push了4次,容量是100,远没越界;pop了一次,tail从4减到3,也没越界。程序会正常输出4和100。A项错在把“有边界缺陷”等同于“当前运行必错”。 B项说“ManyData可用于构造队列”。队列要求先进先出,push和pop要在两端:push_front加头,pop_back删尾,或者push_back加尾,pop_front删头。本题push和pop都在tail端,是后进先出,这是栈的行为。命题人利用“ManyData”这个名字暗示“多数据”,诱导错误联想,B项必错。 C项说“cout<<myData.__data[0]不会报错”。这是C++零基础最易错点:私有成员外部不可见,直接访问会编译不通过。题目故意用__data前缀制造“看起来像内部变量”的假象,实则外部不可见。C项错。 D项说“可以为push/pop增加异常处理,否则可能导致运行时错误”。逻辑成立:push时tail可能>=capacity,pop时tail可能<=0,这两种情况都会越界;增加异常处理(比如抛出exception或返回错误码)可以提前捕获,避免运行时崩溃。而且命题人特意强调“不一定局限于上述代码中的main函数”,意思是即使main里push/pop数量少,只要用户误用(比如循环push 200次),类本身的设计缺陷仍会导致错误。D项正确。

【思考心法】拿到这种类实现题,先问自己三个问题: 1)访问权限:成员变量是public还是private?外部能直接读写吗? 2)操作方向:push/pop分别在哪个端?是先进先出还是后进先出? 3)边界条件:new出来的数组容量有限,push会不会溢出?pop会不会空指针/负索引? 按这个顺序推,选项自然就能排除。

【避坑提醒】

【考频与趋势】 指针与内存相关题目在题库共考过77题,覆盖6个级别,逐年分布:2007年1题、2023年13题、2024年17题、2025年25题、2026年16题、null年5题;分赛事:GESP五级22题、GESP七级18题、GESP四级17题、GESP六级16题、GESP八级3题、NOIP普及组初赛1题。其中GESP六级16题,说明这个级别对指针与内存、类封装的考查非常稳定。

【预测】 从数据看,2023-2026年指针与内存类题目数量明显上升(2023年13题→2026年16题),且GESP六级占比稳定在16题,说明该类考点是六级C++的必考项。未来GESP六级C++仍会高频考查类成员访问权限、动态数组边界检查、构造函数/析构函数异常安全等知识点。命题人可能会继续用“看似正常但隐藏越界”的代码片段,或者把栈/队列的实现细节混在一起,让学生区分操作方向与访问权限。暂无足够依据预测具体题型变化,但“封装+边界+异常”的组合大概率仍是主流。

综上,本题正确答案是D。

同考点真题

在 OI伴学 里做这道题
登录后可计时作答、查看完整六段式解析,并按你的错题自动生成同类练习。
去刷题先做一次 AI 学情诊断