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 = 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)可以更安全的获取到尾部的迭代器
许可协议:
CC BY 4.0