C++ 初学者常见错误:如何避免它们

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言

C++ 是一种强大且灵活的编程语言,赋予开发者对系统资源的巨大控制权。然而,这种自由也伴随着重大责任。初学者程序员常常会犯同样的错误,这些错误可能导致难以发现的漏洞、内存泄漏和未定义行为。本文将探讨C++ 初学者最常见的错误,并展示如何避免它们。



1. 内存泄漏与错误的资源管理



问题:通过 new/delete 手动管理内存

最常见的错误之一是忘记为通过 new 创建的对象调用 delete,这会导致内存泄漏。

void example() {    int* ptr = new int(42);    // ... 某些代码 ...    // 忘记调用 delete ptr;}

在更复杂的情况下,如果在 new 和 delete 之间发生异常,内存同样无法释放。



解决方案:使用 RAII 和智能指针

C++11 及更高标准提供了智能指针,可以自动管理对象的生命周期。

#include <memory>

void example() { std::unique_ptr<int> ptr = std::make_unique<int>(42); // 离开作用域时内存将自动释放}

对于数组,请使用 std::vector 代替手动管理:

// 错误做法:int* arr = new int[100];// ... 操作 ...delete[] arr;

// 正确做法:std::vector<int> arr(100);// 内存自动管理


2. 未定义行为



问题:数组索引越界

C++ 对原始数组没有内置的边界检查。访问数组外的元素是典型的未定义行为。

int arr[5] = {1, 2, 3, 4, 5};arr[10] = 42; // 未定义行为!可能“正常工作”,也可能崩溃


解决方案:使用 std::array 和 std::vector 的 at() 方法

#include <vector>#include <array>

std::array<int, 5> arr = {1, 2, 3, 4, 5};// arr.at(10) 会抛出 std::out_of_range 异常

std::vector<int> vec = {1, 2, 3};vec.at(5); // 安全的边界检查


问题:使用未初始化的变量

int x;std::cout << x; // 未定义行为:x 未初始化

务必初始化变量:

int x = 0;int* ptr = nullptr;


3. 指针与引用的混淆



问题:返回指向局部对象的指针

int* getBadPointer() {    int local = 42;    return &local; // 错误!local 在函数退出时被销毁}

这会导致悬空指针。使用这种指针是未定义行为。



解决方案:按值返回或使用智能指针

// 按值返回(简单类型的首选)int getValue() {    return 42;}

// 对于动态对象返回智能指针std::unique_ptr<MyClass> createObject() { return std::make_unique<MyClass>();}


问题:引用与指针的混淆

引用不能是 nullptr,也不能重新赋值。指针可以。初学者常试图将 nullptr 传递给期望引用的函数。

void process(int& ref) {    // ref 保证引用一个存在的对象}

int* ptr = nullptr;// process(*ptr); // 错误!解引用 nullptr 是未定义行为

当对象必须存在时使用引用,当可能为 null 时使用指针(或 std::optional)。

博客

书籍推荐