当前位置: 首页 > news >正文

C++中的内存管理(一)

文章目录

    • 动态分配和初始化对象
    • 内存耗尽
    • 释放动态内存
      • delete之后重置指针

C++定义了两个运算符来分配和释放内存。 new分配内存, delete释放 new分配的内存。值得注意的是,使用这两个指针的类通常不能依赖于默认的拷贝、赋值、析构函数。

#include <cstring>
#include <iostream>class MyString {
private:char* data;
public:MyString(const char* str = "") {data = new char[strlen(str) + 1];strcpy(data, str);}// 拷贝构造(深拷贝)MyString(const MyString& other) {data = new char[strlen(other.data) + 1];strcpy(data, other.data);}// 赋值运算符(深拷贝)MyString& operator=(const MyString& other) {if (this != &other) {delete[] data;data = new char[strlen(other.data) + 1];strcpy(data, other.data);}return *this;}// 析构函数~MyString() {delete[] data;}void print() const {std::cout << data << std::endl;}
};int main() {MyString a("Hello");MyString b = a;  // 调用拷贝构造b.print();MyString c;c = a;           // 调用赋值运算符c.print();
}
  • 默认拷贝构造 / 赋值运算符 只是做浅拷贝,会直接复制指针值。

  • 两个对象就会指向同一块堆内存,析构时会导致重复释放(double free)。

  • 自己写可以确保做深拷贝,让每个对象管理自己独立的内存。

动态分配和初始化对象

在自由空间分配的内存是无名的,因此new无法为其分配的对象命名,而是返回一个指向该对象的指针。

默认情况下,动态分配的对象是默认初始化的,这意味着内置类型或组合类型对象的值将是未定义的,而类类型对象将用默认构造函数初始化。

int *pi = new int; //指向未定义的int
string *ps = new string; //指向初始化为空的string

除了默认初始化之外,还可以通过传统的构造方式(圆括号)、列表初始化(花括号):

int *pi = new int(1024); //指向对象的值为1024
string *ps = new string(10, '9'); //指向值为“9999999999”vector<int> *pv = new vector<int>{0, 1, 2, 3, 4};

值得注意的是,传统构造初始化,若不加参数,则进行值初始化。对于定义了自己的构造函数的类类型来说,值初始化和默认初始化都是通过默认构造函数来初始化。但是对于内置类型:值初始化有着良好定义的值,而默认初始化的对象的值则是未定义的。类似的,对于类中的内置类型成员,如果没有显示初始化,而是仅使用默认构造函数的话,则它们的值也是未定义的。

  • 配合auto
auto p1 = new auto(obj); //指向一个与obj相同类型的对象,该对象使用obj初始化
  • 配合const
const int *pci = new const int(1024);
const string *pcs = new const string;

内存耗尽

int *p1 = new int; //如果分配失败,new抛出std::bad_alloc
int *p2 = new (nothrow) int; //如果分配失败,new返回一个空指针

释放动态内存

我们传递给delete的指针必须指向动态分配的内存,或者是一个空指针。释放一块并非new分配的内存,或者将相同的指针释放多次,其行为是未定义的。

使用new的动态内存管理非常容易出错:

  • 忘记delete内存,造成内存泄漏;
  • 使用已经释放掉的对象,悬空指针;
  • 同一块内存被释放两次。

delete之后重置指针

当我们在delete一个指针之后,指针值就无效了。但在很多机器上指针依然保存着已经释放掉的动态内存地址。即成了悬空指针。虽然可以在delete之后,将其赋值为nullptr,但这只提供了有限的保护:

int *p(new int(42)); //p指向动态内存
auto q = p; //q指向相同的动态内存
delete p; //p、q都无效
p = nullptr; //重置p

上列中并没有重置到指针q,还是容易出错。在实际系统中,查找指向相同内存的所有指针是异常困难的。因此需要更加安全的方法来使用动态内存。

http://www.dtcms.com/a/331442.html

相关文章:

  • BitDock——让你的Windows桌面变为Mac
  • 【ai写代码】lua-判断表是否被修改
  • Mysql基本使用语句(一)
  • [激光原理与应用-271]:理论 - 波动光学 - 电磁波谱,光是一种可视化的电磁波
  • 广义矩估计随机近似中1.2和2.1的差异
  • 获取iframe中canvas画面
  • 爬虫数据存储全攻略:从 Robots 协议到文件存储
  • C++11新特性深度解析
  • Linux软件下载菜单脚本
  • Effective C++ 条款41:理解隐式接口和编译期多态
  • 系统设计——DDD领域模型驱动实践
  • 深入浅出词向量(Word2Vec):从理论到实践
  • 数据结构初阶(13)排序算法-选择排序(选择排序、堆排序)(动图演示)
  • 【Java 后端】Spring Boot 集成 JPA 全攻略
  • HTTPS 工作原理
  • 电池充放电测试仪厂家:技术深耕与场景驱动的行业进阶
  • Java使用Apache POI读取Excel文件
  • Vue浅学
  • 深入解析 GitHub Actions 工作流文件编写:从入门到实战
  • 简单的 HTTPS 学习
  • 第四天-创建一个Classic CAN(经典CAN2.0)/CANFD的系统描述ARXML文件
  • 读From GPT-2 to gpt-oss: Analyzing the Architectural Advances
  • IPv6互联网地址解析
  • 从合规到卓越:全星QMS如何成为制造企业的质量战略引擎
  • linux 软硬链接详解
  • 《算法导论》第 25 章:所有结点对的最短路径问题
  • 计算机视觉CS231n学习(8)
  • 12 ABP Framework 租户管理
  • 介绍一下 自动驾驶 感知多任务训练模型设计
  • 面试题:如何用Flink实时计算QPS