数组倒序
将一组数组倒序排序,如{1,2,3,4,5}
=>{5,4,3,2,1}
错误写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #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(推荐):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #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++) { 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(只适合索引长度为奇数):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #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; } 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; }
|
冒泡排序
错误写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #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; }
|
错误原因:虽然可以正确的对数组进行排序,但并不是冒泡排序
正确展示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #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; }
|
饮品制作(多态案例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| #include <iostream> #include <string>
using namespace std;
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; }
|
出错原因:虽然代码没问题,但是有更好的优化空间
优化代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| #include <iostream> #include <string>
using namespace std;
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; }
|
计算机组装(多态案例)
错误示范:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| #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++的一个重要原则,特别是当你计划通过基类指针管理派生类对象时。
原代码虽然可能在某些编译器上”看起来”正常工作,但实际上存在未定义行为,这可能导致难以调试的问题。
正确示范:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
| #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; }
|
迭代器删除错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 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); set<int>::iterator beg = st1.begin(); advance(beg, 4); set<int>::iterator era01 = st1.erase(beg); cout << "删除后下个元素是: " << *era01 << endl; PrintSet(st1);
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)
这种写法
修改方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| 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); set<int>::iterator beg = st1.begin(); advance(beg, 4); set<int>::iterator era01 = st1.erase(beg); cout << "删除后下个元素是: " << *era01 << endl; PrintSet(st1);
beg = st1.begin(); advance(beg, 3); 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)
可以更安全的获取到尾部的迭代器