刚学完C和C++大一课程,看《构建之法》时,书中讲的很多问题就像在说我自己。过去写代码只想着功能实现,吃了不少苦头。这本书让我明白,那些让我头疼的问题,其实有更好的解决办法。
问题一:所有代码都堆在main里
写“学生成绩管理系统”时,我把输入、计算、输出全塞进main函数。代码很快超过300行,想加个按平均分排序的功能时,自己都找不到该在哪里插入。修一个地方可能搞坏另一个地方,调试起来特别费劲,经常在循环和条件判断里打转。
书中指出: 这叫“意大利面条式代码”。结构混乱让代码难读、难改、难调,完全谈不上可维护性。我当时只图一时方便,没考虑后面要修改和扩展。
我的改进:
拆分成函数: 把不同功能写成单独函数,比如inputStudents(), calcAverage(), sortStudents(), printStudents()。每个函数只做一件事。main里就剩几个清晰的函数调用。
用头文件和源文件: 在C++里,把学生数据struct和操作函数声明放student.h,具体实现放student.cpp。main.cpp只管调用。这样修改一个功能时,其他文件不受影响。
变量函数起好名: studentList 比 list 清楚,findStudentById(int id) 比 search() 明确。好名字省了看注释的时间,一周后自己还能看懂。
问题二:指针和内存管理混乱
练习链表操作时,new了节点,链接起来测试好像没问题。后来加删除功能,程序动不动就崩溃或输出乱码。花大量时间用cout打印地址找哪里指错了,或者忘了delete。一个内存错误就能折腾一晚上,效率极低。
书中指出: C/C++里内存管理不当是崩溃的主要原因。指针乱用、忘了释放或访问已释放内存都是大问题。我当时对资源管理没概念。
我的改进:
明确谁管内存:定好规矩,比如createNode()负责new并返回指针,deleteList(Node* head)负责遍历整个链表delete。调用者用完链表必须调deleteList。
指针用前判空:解引用指针前,习惯性加 if (ptr != nullptr),避免很多崩溃。特别是函数参数可能为空时。
C++用智能指针:学用 unique_ptr 和 shared_ptr。它们能自动管理内存,极大减少 new/delete 带来的错误。写链表节点就用 std::unique_ptr
用工具查内存:学会用valgrind或IDE自带的内存检测工具跑程序,能快速精准地找到泄漏和非法访问,比肉眼调试快很多。
问题三:调试全靠打印,效率低
以前写完代码,运行结果不对,就在可能出错的地方疯狂加 printf 或 cout 打印变量值。编译、运行、看输出、猜错在哪、再改代码...循环无数次。尤其是指针或逻辑复杂时,像盲人摸象。找个数组越界(i <= N 错写成 i < N)可能花几小时,修改后还不能保证其他地方没坏。
书中指出: 依赖手动打印调试效率极低,覆盖不全,也没法重复用。这不是工程化的方法,浪费大量时间。
我的改进:
学会用调试器: 掌握 GDB 或 IDE 的调试功能。这比打印快得多,能直接看到运行时的状态。定位数组越界问题几分钟就能搞定。
给关键函数写小测试: 比如写个 testCalcAverage() 函数,里面创建几个已知成绩的学生,调用 calcAverage(),用assert或if检查返回值是不是预期。改完代码跑一下测试,能快速知道有没有破坏原有功能,不用再手动测整个流程。
缩小问题范围: 遇到崩溃或错误,先试着把大程序简化,构造一个只包含十几行代码的最小例子能复现问题。去掉无关代码后,根因更容易暴露。
总结
《构建之法》让我意识到,过去只求代码“能跑”的做法问题很大。代码堆在main里导致混乱难改,指针内存管理不好导致崩溃难查,调试方法原始导致效率低下,浪费很多时间。
这本书给我的最大帮助是:好的编程习惯要尽早养成。即使写小作业:
拆解组织代码: 把代码按功能拆开、分文件放、起好名字。代码清晰了,修改调试都容易。
管好内存资源: C++ 多用智能指针,明确资源归属。程序稳定了,不用总担心崩溃。
用工具提效率: 掌握调试器,给重要功能写点小测试。调试快了,省下的时间能学更多。
遇问题先简化: 缩小范围找根因,不瞎猜。
开始养成这些习惯可能需要多花点心思,但能省下无数调试的夜晚,代码也更可靠。邹欣老师让我明白,按工程化的方法写代码,才是高效学习的正道,也能为以后做更大的项目打好基础。