C++期末救命讲义 按样题考点整理
⚠️ 第36、37、41题

05 易错陷阱:代码看着没红,不代表它安全

这页专门处理问答/改错题。答题套路固定:指出问题 → 说后果 → 给修改。

第36题

野指针:free 以后,指针不会自动变 NULL

char *str = (char *)malloc(100);
strcpy(str, "hello");
free(str);
if (str != NULL) {
    strcpy(str, "world");
    printf(str);
}
标准说法 free(str) 只释放 str 指向的内存,不会把 str 变量本身改成 NULL。str 还保存着旧地址,但那块内存已经不归你管了,所以 str 成为野指针。
代码真实发生的事考场怎么说
free(str);内存被还回去释放后不能再用。
if (str != NULL)大概率仍然成立这个判断没用,因为 str 没自动变 NULL。
strcpy(str, "world")往已释放内存写结果不可预料,可能崩溃,可能看似正常。
✅ 修改
free(str);
str = NULL;
第37题

浅拷贝:两个对象指向同一块内存

题目场景:类中有指针成员 pFirstName,执行 Mike = John 时,如果没有自己重载赋值运算符,就会调用默认赋值函数,逐个成员直接复制。
// 重点不是完整类定义,而是这个危险动作:
Person Mike("Mike", 25);
Person John("John", 30);

Mike = John;  // 默认赋值:只复制指针地址,不复制指针指向的内容
人话翻译 默认赋值像“只复制快递单号”,不是重新买一份东西。结果 Mike 和 John 的指针都指向同一块姓名内存。
内存泄漏Mike 原来指向的内存没人释放了,像旧钥匙丢了,房子还占着。
双重释放两个对象析构时释放同一块内存,像同一张票退两次,后果不可预料。
✅ 解决
Person& Person::operator=(const Person& rhs) {
    if (this == &rhs) return *this;
    delete [] pFirstName;
    pFirstName = new char[strlen(rhs.pFirstName) + 1];
    strcpy(pFirstName, rhs.pFirstName);
    return *this;
}
记法 类里有 char*int* 这种自己管内存的指针,就想到:析构、拷贝构造、赋值运算符,三件套要一起管。
第41题

私有成员:外面不能直接碰

class Person {
public:
    double getHeight() { return this->height; }
    void setHeight(double height) { this->height = height; }
private:
    double height;
};

int main() {
    Person p;
    p.height = 1.85;       // 错
    cout << p.getHeight();
}
✅ 修正
Person p;
p.setHeight(1.85);
cout << p.getHeight() << '\n';
考场说法 height 是 private 私有成员,只能在类内部直接访问。类外要通过 public 的 setter/getter 间接访问。
总背诵

改错题固定回答格式

第一句:这里有 bug,问题是……
第二句:原因是……,会导致……
第三句:修改方法是……