Effective C++ 条款16: 成对使用new和delete时要采用相同形式

Effective C++ 条款16:成对使用new和delete时要采用相同形式


核心思想动态分配数组时使用new[]delete[],分配单个对象时使用newdelete,两者必须严格匹配,否则导致未定义行为(内存泄漏或程序崩溃)。

⚠️ 1. 混用形式的灾难性后果

错误配对示例

// 场景1:数组分配用delete释放
std::string* strArray = new std::string[10];
delete strArray;  // 错误!应为delete[] → 内存泄漏/程序崩溃

// 场景2:单个对象用delete[]释放
std::string* singleStr = new std::string;
delete[] singleStr;  // 错误!应为delete → 程序崩溃

内存布局差异

分配方式内存布局释放所需操作
new[对象数据]调用1次析构函数
new[][数组长度][对象1][对象2]…调用n次析构函数+长度读取

🚨 2. 解决方案:严格配对使用

正确配对规则

// 单个对象
Type* singleObj = new Type;    // 分配
delete singleObj;              // 释放

// 对象数组
Type* objArray = new Type[10]; // 分配
delete[] objArray;             // 释放

typedef陷阱与修复

// 危险:隐藏数组类型
typedef std::string AddressLines[4]; 
std::string* pal = new AddressLines; // 实际是new string[4]

delete pal;     // 错误!未使用delete[] → 仅析构第一个元素
delete[] pal;   // 正确!严格匹配new[]

⚖️ 3. 关键原则与注意事项
原则说明违反后果
new/delete配对单个对象分配释放必须成对使用对象析构不全
new[]/delete[]配对数组分配释放必须成对使用内存泄漏或程序崩溃
避免typedef数组使用std::vectorstd::array替代数组typedef消除配对认知负担
智能指针优先使用std::vector/unique_ptr<T[]>管理数组自动匹配释放形式

现代C++最佳实践

// 替代原生数组(推荐)
std::vector<std::string> addressLines(4);  // 自动管理内存

// 需要裸指针时使用智能指针数组版本
auto pal = std::make_unique<std::string[]>(4); // C++14+
pal[0] = "1600 Pennsylvania Ave";
// 自动调用delete[]释放

类型安全封装

template<typename T>
using ArrayPtr = std::unique_ptr<T[]>;  // 安全数组指针别名

ArrayPtr<std::string> createAddress() {
    return std::make_unique<std::string[]>(4);
} // 自动正确释放

💡 关键原则总结

  1. 严格配对原则
    • newdelete
    • new Type[n]delete[]
    • 绝对禁止交叉使用
  2. typedef数组的危险性
    • 避免对数组类型使用typedef → 改用std::vectorstd::array
    • 必须typedef时显式标注delete[]
  3. 智能指针自动匹配
    • std::unique_ptr<T[]>自动使用delete[]
    • std::shared_ptr需自定义数组删除器

错误示例诊断:typedef导致的隐性错误

typedef int BufferType[1024];
int* buffer = new BufferType;  // 实际分配数组

delete buffer;  // 错误!应为delete[] → 仅释放第一个元素

安全修复方案

// 方案1:显式使用delete[]
delete[] buffer;  // 正确配对

// 方案2:改用标准容器(推荐)
std::array<int, 1024> buffer;  // 栈分配自动管理

// 方案3:智能指针管理
auto buffer = std::make_unique<int[]>(1024);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值