N

Norlcayn的博客

A text-focused Halo theme

  • 首页
  • 文章
  • 默认分类
  • 关于
主页 CPP错误案例
文章

CPP错误案例

发表于 2025-06-28 更新于 昨天
作者 Administrator
36~46 分钟 阅读

数组倒序

将一组数组倒序排序,如{1,2,3,4,5}=>{5,4,3,2,1}

错误写法:

#include <iostream>

using namespace std;

int main() {
// 数组倒序
int arr_02[] = { 1,2,3,4,5 };
length = sizeof(arr_02) / sizeof(arr_02[0]);
for (int i = 0; i < length; i++)
{
int reverse_index = length - 1 - i;
if (arr_02[i] == arr_02[reverse_index]) {
continue;
}
else {
int tmp = arr_02[i];
arr_02[i] = arr_02[reverse_index];
arr_02[reverse_index] = tmp;
}
}

for (int i = 0; i < length; i++)
{
cout << arr_02[i];
}

return 0;
}

解释:当判断到数组中间时,也就是arr_02[i] == arr_02[reverse_index]会跳过这次循环而非打断循环,正确的应该是停止循环或者length/2

正确写法1(推荐):

#include <iostream>

using namespace std;

int main() {
// 数组倒序
int arr_02[] = { 1,2,3,4,5 };
length = sizeof(arr_02) / sizeof(arr_02[0]);
for (int i = 0; i < length / 2; i++)// 长度÷2,表示将前半部分和后半部分互换位置
{
int reverse_index = length - 1 - i;
int tmp = arr_02[i];
arr_02[i] = arr_02[reverse_index];
arr_02[reverse_index] = tmp;
}

for (int i = 0; i < length; i++)
{
cout << arr_02[i];
}

return 0;
}

正确写法2(只适合索引长度为奇数):

#include <iostream>

using namespace std;

int main() {
// 数组倒序
int arr_02[] = { 1,2,3,4,5 };
length = sizeof(arr_02) / sizeof(arr_02[0]);
for (int i = 0; i < length; i++)
{
int reverse_index = length - 1 - i;
if (arr_02[i] == arr_02[reverse_index]) {
break;// 当执行到中间部分停止循环,数组长度为偶数就不能这么写,因为无法获得到中间索引,所以break永远不会被执行到
}
else {
int tmp = arr_02[i];
arr_02[i] = arr_02[reverse_index];
arr_02[reverse_index] = tmp;
}
}

for (int i = 0; i < length; i++)
{
cout << arr_02[i];
}

return 0;
}

冒泡排序

错误写法:

#include <iostream>
#include <string>

using namespace std;

void BubbleSort(int arr[],int length) {

for (int i = 0; i < length; i++)
{
for (int j = 0; j < length; j++)
{
if (arr[i] < arr[j]) {
int tmp = arr[i];
                arr[i] = arr[j];
                arr[j] = tmp;
}
}
}
}

int main() {
int arr[] = { 5,4,3,2,1 };

    BubbleSort(arr,5);

for(int i = 0; i < 5; i++)
{
cout << arr[i] << " ";
}

    return 0;
}

错误原因:虽然可以正确的对数组进行排序,但并不是冒泡排序

正确展示:

#include <iostream>
#include <string>

using namespace std;

void BubbleSort(int arr[],int length) {

for (int i = 0; i < length - 1; i++)
{
for (int j = 0; j < length - 1 - i; j++)
{
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
}
}
}
}

int main() {
int arr[] = { 5,4,3,2,1 };

    BubbleSort(arr,5);

for(int i = 0; i < 5; i++)
{
cout << arr[i] << " ";
}

    return 0;
}

饮品制作(多态案例)

#include <iostream>
#include <string>

using namespace std;

/* 
    制作饮品案例:
    1. 制作咖啡
    2. 制作茶

    抽象类:
    1. 制作饮品抽象类

    制作咖啡步骤:
    1. 煮水
    2. 冲泡咖啡
    3. 倒入杯中
    4. 加糖和牛奶

    制作茶步骤:
    1. 煮水
    2. 冲泡茶
    3. 倒入杯中
    4. 加柠檬
*/

class MakeDrinks {
public:
    void BoilWater() {
        cout << "煮水" << endl;
    }

    void PourIntoCup() {
        cout << "倒入杯中" << endl;
    }

    virtual void PrepareCoffe() {};
    virtual void BrewTea() {};
    virtual void AddSugarAndMilk() {};
    virtual void AddLemon() {};
};

class MakeCoffee : public MakeDrinks {
public:
    void PrepareCoffe() {
        cout << "冲泡咖啡" << endl;
    }

    void AddSugarAndMilk() {
        cout << "加糖和牛奶" << endl;
    }
};

class MakeTea : public MakeDrinks {
public:
    void BrewTea() {
        cout << "冲泡茶" << endl;
    }

    void AddLemon() {
        cout << "加柠檬" << endl;
    }
};

int main() {
    MakeDrinks* makeCoffee = new MakeCoffee();
    makeCoffee->BoilWater();
    makeCoffee->PrepareCoffe();
    makeCoffee->PourIntoCup();
    makeCoffee->AddSugarAndMilk();
    cout << "*****************************************"<< endl;
    MakeDrinks* makeTea = new MakeTea();
    makeTea->BoilWater();
    makeTea->BrewTea();
    makeTea->PourIntoCup();
    makeTea->AddLemon();

    return 0;
}

出错原因:虽然代码没问题,但是有更好的优化空间

优化代码:

#include <iostream>
#include <string>

using namespace std;

/* 
    制作饮品案例:
    1. 制作咖啡
    2. 制作茶

    抽象类:
    1. 制作饮品抽象类

    制作咖啡步骤:
    1. 煮水
    2. 冲泡咖啡
    3. 倒入杯中
    4. 加糖和牛奶

    制作茶步骤:
    1. 煮水
    2. 冲泡茶
    3. 倒入杯中
    4. 加柠檬
*/

class MakeDrinks {
public:
    // 煮水
    virtual void BoilWater() = 0;

    // 冲泡
    virtual void Brew() = 0;

    // 倒入杯中
    virtual void PourIntoCup() = 0;

    // 加调料
    virtual void AddCondiments() = 0;

    void MakeDrink() {
        BoilWater();
        Brew();
        PourIntoCup();
        AddCondiments();
    }
};

class MakeCoffee : public MakeDrinks {
public:
    void BoilWater() override {
        cout << "煮水" << endl;
    }

    void Brew() override {
        cout << "冲泡咖啡" << endl;
    }

    void AddCondiments() override {
        cout << "加糖和牛奶" << endl;
    }

    void PourIntoCup() override {
        cout << "倒入杯中" << endl;
    }
};

class MakeTea : public MakeDrinks {
public:
    void BoilWater() override {
        cout << "煮水" << endl;
    }

    void Brew() override {
        cout << "冲泡茶叶" << endl;
    }

    void AddCondiments() override {
        cout << "加柠檬" << endl;
    }

    void PourIntoCup() override {
        cout << "倒入杯中" << endl;
    }
};

int main() {
    MakeDrinks *makeDrinks = new MakeCoffee();
    makeDrinks->MakeDrink();
    cout << "---------------------" << endl;
    makeDrinks = new MakeTea();
    makeDrinks->MakeDrink();

    return 0;
}

计算机组装(多态案例)

错误示范:

#include <iostream>
#include <string>

using namespace std;
// 零件基类(抽象类)
class CPU {
public:
    virtual void calculate() = 0;
};

class GraphicsCard {
public:
    virtual void display() = 0;
};

class Memory {
public:
    virtual void storeData() = 0;

};

// 电脑类
class Computer {
public:
    CPU* cpu;
    GraphicsCard* graphicsCard;
    Memory* memory;

    Computer(CPU* cpu, GraphicsCard* graphicsCard, Memory* memory) {
        this->cpu = cpu;
        this->graphicsCard = graphicsCard;
        this->memory = memory;
    }

    void run() {
        cpu->calculate();
        graphicsCard->display();
        memory->storeData();
    }

    // 防止内存泄露
    ~Computer() {
        if (cpu != nullptr) {
            delete cpu;
            cpu = nullptr;
        }

        if (graphicsCard != nullptr) {
            delete graphicsCard;
            graphicsCard = nullptr;
        }

        if (memory != nullptr) {
            delete memory;
            memory = nullptr;
        }
    }
};

// 具体实现类
class IntelCPU : public CPU {
public:
    void calculate() override {
        std::cout << "Intel CPU 计算中..." << std::endl;
    }
};

class AmdCPU : public CPU {
public:
    void calculate() override {
        std::cout << "Amd CPU 计算中..." << std::endl;
    }
};

class NvidiaGraphicsCard : public GraphicsCard {
public:
    void display() override {
        std::cout << "Nvidia 显卡 显示中..." << std::endl;
    }
};

class AmdGraphicsCard : public GraphicsCard {
public:
    void display() override {
        std::cout << "Amd 显卡 显示中..." << std::endl;
    }
};

class SamsungMemory : public Memory {
public:
    void storeData() override {
        std::cout << "Samsung 内存 存储数据中..." << std::endl;
    }
};

class KingstonMemory : public Memory {
public:
    void storeData() override {
        std::cout << "Kingston 内存 存储数据中..." << std::endl;
    }
};

int main() {
    Computer *computer_01 = new Computer(new IntelCPU(), new NvidiaGraphicsCard(), new SamsungMemory());
    Computer *computer_02 = new Computer(new AmdCPU(), new AmdGraphicsCard(), new KingstonMemory());
    Computer *computer_03 = new Computer(new AmdCPU(), new NvidiaGraphicsCard(), new KingstonMemory());

    cout << "电脑_01开启:" << endl;
    computer_01->run();
    cout << endl;

    cout << "电脑_02开启:" << endl;
    computer_02->run();
    cout << endl;

    cout << "电脑_03开启:" << endl;
    computer_03->run();
    cout << endl;

    delete computer_01; 
    delete computer_02;
    delete computer_03;


    return 0;
}

错误原因:

如果一个类包含虚函数,它几乎总是需要一个虚析构函数。 这是C++的一个重要原则,特别是当你计划通过基类指针管理派生类对象时。

原代码虽然可能在某些编译器上”看起来”正常工作,但实际上存在未定义行为,这可能导致难以调试的问题。

正确示范:

#include <iostream>
#include <string>

using namespace std;
// 零件基类(抽象类)
class CPU {
public:
    virtual void calculate() = 0;
    virtual ~CPU() = 0;
};

class GraphicsCard {
public:
    virtual void display() = 0;
    virtual ~GraphicsCard() = 0;
};

class Memory {
public:
    virtual void storeData() = 0;
    virtual ~Memory() = 0;
};

// 实现纯虚析构函数,防止报错
CPU::~CPU() {}
GraphicsCard::~GraphicsCard() {}
Memory::~Memory() {}

// 电脑类
class Computer {
public:
    CPU* cpu;
    GraphicsCard* graphicsCard;
    Memory* memory;

    Computer(CPU* cpu, GraphicsCard* graphicsCard, Memory* memory) {
        this->cpu = cpu;
        this->graphicsCard = graphicsCard;
        this->memory = memory;
    }

    void run() {
        cpu->calculate();
        graphicsCard->display();
        memory->storeData();
    }

    // 防止内存泄露
    ~Computer() {
        if (cpu != nullptr) {
            delete cpu;
            cpu = nullptr;
        }

        if (graphicsCard != nullptr) {
            delete graphicsCard;
            graphicsCard = nullptr;
        }

        if (memory != nullptr) {
            delete memory;
            memory = nullptr;
        }
    }
};

// 具体实现类
class IntelCPU : public CPU {
public:
    void calculate() override {
        std::cout << "Intel CPU 计算中..." << std::endl;
    }

    ~IntelCPU() override {
        std::cout << "Intel CPU 析构函数" << std::endl;
    }
};

class AmdCPU : public CPU {
public:
    void calculate() override {
        std::cout << "Amd CPU 计算中..." << std::endl;
    }

    ~AmdCPU() override {
        std::cout << "Amd CPU 析构函数" << std::endl;
    }
};

class NvidiaGraphicsCard : public GraphicsCard {
public:
    void display() override {
        std::cout << "Nvidia 显卡 显示中..." << std::endl;
    }

    ~NvidiaGraphicsCard() override {
        std::cout << "Nvidia 显卡 析构函数" << std::endl;
    }
};

class AmdGraphicsCard : public GraphicsCard {
public:
    void display() override {
        std::cout << "Amd 显卡 显示中..." << std::endl;
    }

    ~AmdGraphicsCard() override {
        std::cout << "Amd 显卡 析构函数" << std::endl;
    }
};

class SamsungMemory : public Memory {
public:
    void storeData() override {
        std::cout << "Samsung 内存 存储数据中..." << std::endl;
    }

    ~SamsungMemory() override {
        std::cout << "Samsung 内存 析构函数" << std::endl;
    }
};

class KingstonMemory : public Memory {
public:
    void storeData() override {
        std::cout << "Kingston 内存 存储数据中..." << std::endl;
    }

    ~KingstonMemory() override {
        std::cout << "Kingston 内存 析构函数" << std::endl;
    }
};

int main() {
    Computer *computer_01 = new Computer(new IntelCPU(), new NvidiaGraphicsCard(), new SamsungMemory());
    Computer *computer_02 = new Computer(new AmdCPU(), new AmdGraphicsCard(), new KingstonMemory());
    Computer *computer_03 = new Computer(new AmdCPU(), new NvidiaGraphicsCard(), new KingstonMemory());

    cout << "电脑_01开启:" << endl;
    computer_01->run();
    cout << endl;

    cout << "电脑_02开启:" << endl;
    computer_02->run();
    cout << endl;

    cout << "电脑_03开启:" << endl;
    computer_03->run();
    cout << endl;

    delete computer_01;
    delete computer_02;
    delete computer_03;


    return 0;
}

迭代器删除错误

void test01() {
set<int> st1;

st1.insert(1);
st1.insert(2);
st1.insert(3);

st1.clear();
cout << "size:" << st1.size() << endl;

for (int i = 0; i < 20; i++)
{
int random = rand() % 20;
st1.insert(random);
}

PrintSet(st1);// 0 1 2 4 5 7 9 11 14 15 16 18
set<int>::iterator beg = st1.begin();
advance(beg, 4);
set<int>::iterator era01 = st1.erase(beg);
cout << "删除后下个元素是: " << *era01 << endl;
PrintSet(st1);// 0 1 2 4 7 9 11 14 15 16 18

set<int>::iterator end = st1.end();
advance(end, -1);
set<int>::iterator era02 = st1.erase(beg, end);
cout << "删除后下个元素是: " << *era01 << endl;
PrintSet(st1);
}

以上代码中,反复使用了beg这个迭代器,实际上,当第一次erase(beg);时,就已经擦除了这个迭代器指向的数据(类似于指针变成了野指针)

其次,由于set容器是双向迭代器,所以不支持advance(end, -1)这种写法

修改方式:

void test01() {
set<int> st1;

st1.insert(1);
st1.insert(2);
st1.insert(3);

st1.clear();
cout << "size:" << st1.size() << endl;

for (int i = 0; i < 20; i++)
{
int random = rand() % 20;
st1.insert(random);
}

PrintSet(st1);// 0 1 2 4 5 7 9 11 14 15 16 18
set<int>::iterator beg = st1.begin();
advance(beg, 4);
set<int>::iterator era01 = st1.erase(beg);
cout << "删除后下个元素是: " << *era01 << endl;
PrintSet(st1);// 0 1 2 4 7 9 11 14 15 16 18

// 第二次删除:删除从第4个元素到倒数第3个元素的范围
beg = st1.begin();
advance(beg, 3);  // 指向4
set<int>::iterator end = st1.end();
set<int>::iterator del_end = prev(end, 3);  // 安全获取倒数第三个元素的位置

set<int>::iterator era02 = st1.erase(beg, del_end);
cout << "删除后下个元素是: " << *era02 << endl;
PrintSet(st1);
}

当删除beg指向的数据后,就应该将beg重置

对于双向迭代器,通过prev(end, 3)可以更安全的获取到尾部的迭代器

CPP
自学系列 编程语言 CPP案例
许可协议:  CC BY 4.0
分享

相关文章

6月 28, 2025

CPP错误案例

数组倒序 将一组数组倒序排序,如{1,2,3,4,5}=>{5,4,3,2,1} 错误写法: #include <iostream> using namespace std; int main() { // 数组倒序 int arr_02[] = { 1,2,3,4,5 }; length =

6月 28, 2025

CPP基础案例

通讯录管理系统 系统需求 通讯录是一个可以记录亲人、好友信息的工具 本案例主要利用C++来实现基础的通讯录管理系统 系统中需要实现的主要功能如下: 添加联系人:向通讯录中添加新人,信息包括姓名、性别、年龄、联系电话、家庭住址,最多记录1000人 显示联系人:显示通讯录中所有联系人信息 删除联系人:按

6月 28, 2025

CPP文件操作

C++文件操作 关键字:ifstream、ofstream、ios:: 程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放 通过文件可以将数据持久化 C++中对文件操作需要包含头文件 文件类型分为两种: 文本文件 - 文件以文本的ASCII码形式存储在计算机中 二进制文件 - 文件以文本

下一篇

Docker起步

上一篇

CPP基础案例

最近更新

  • Hello Halo
  • 状态机
  • 数据表设计规范
  • 缓存优化
  • 事务失效

热门标签

Halo 异常处理 Redisson 并行 Vue 并发 递归 请求限流 SpringAMQP 类加载器

目录

©2026 Norlcayn的博客. 保留部分权利。

使用 Halo 主题 Chirpy