C++初阶--内存管理

简介: C++初阶--内存管理


内存分布

栈(stack):栈是由编译器自动管理的内存区域,用于存储局部变量,函数参数和函数调用信息等。栈的特点是后进先出,它的生命周期与函数的调用关系密切联系。当函数调用结束后,栈上的局部变量会被自动销毁

堆(heap):堆是由程序员手动管理的动态内存区域,用于存储动态分配的对象。通过使用new/delete等操作符来手动申请和释放堆上的内存。堆上的内存生命周期由程序员来负责控制,需要手动释放以避免内存泄漏。

全局存储区(data):全局存储区用于存储全局变量和静态变量。全局变量在程序运行期间一直存在,静态变量具有生命周期,即从声明到程序结束都存在。全局存储区的内存由编译器在程序开始时进行分配,在程序结束时进行自动释放

常量存储区(cost):常量存储区用于存储常量值,例如字符串常量,数字等。这部分内存通常是只读的,不可修改。

new/delete

在C语言中,我们是用malloc和free来进行动态内存管理的,而在C++中,我们习惯使用new/delete来进行动态内存管理。

基本用法

class A
{
private:
  int _a;
public:
  A(int a=0)
    :_a(a)
  {
    cout << "A()" << endl;
  }
  ~A()
  {
    cout << "~A()" << endl;
  }
};
int main()
{
  //new
  int* p1 = new int;
  *p1 = 20;
  int* p2 = new int[10];
  p2[0] = 1;
  p2[1] = 2;
  int* p3 = new int(4);
  int* p4 = new int[10] {1, 2, 3};
  delete p1;
  delete[] p2;
  delete p3;
  delete[] p4;
  //对于自定义类型来说
  //new的本质:开空间+使用构造函数
  A aa1;
  A aa2;
  A aa3;
  A* p5 = new A[3]{ aa1,aa2,aa3 };
  A* p6 = new A[3];
  A* p7 = new A[3]{ A(1),A(2),A(3) };
  A* p8 = new A[3]{ 1,2,3 };
  delete[] p5;
  delete[] p6;
  delete[] p7;
  delete[] p8;
  return 0;
}

基本用法:

有自定义类型时:

malloc/free和new/delete的区别

进一步理解

class Stack 
{
private:
  int* _a;
  int _top;
  int _capacity;
public:
  Stack(int capacity = 4)
    :_a(new int[capacity]),
    _top(0),
    _capacity(capacity)
  {
    cout << "Stack(int capacity):" << endl;
  }
  ~Stack()
  {
    cout << "~Stack()" << endl;
    delete[] _a;
    _a = nullptr;
    _top = 0;
    _capacity = 0;
  }
};
int main()
{
  Stack* p1 = new Stack;
  delete p1;
  Stack* p2 = (Stack*)operator new(sizeof(Stack));
  operator delete(p2);
  Stack* p3 = new Stack[10];
  //delete[] p3;
  delete p3;
  A* p4 = new A[10];
  delete p4;
  return 0;
}

空间的开辟:

操作数new和delete:

当把析构函数屏蔽了,使用delete p3,为什么可以通过编译:

*

new和delete的实现原理

定位new(了解)

定位new是一种特殊的用法,用于在指定的内存位置上创建对象。通常情况下,使用new关键字会在堆内存中动态分配一块适当的空间大小,并在该内存上构造一个对象。而定位new则允许我们预先分配一块内存,并在该内存上构造对象

语法形式:new(address)Type(arguments)

int main()
{
  A* p1 = (A*)operator new(sizeof(A));
  //不能显示调用构造函数
  //p1->A(1);
  //可以这样操作
  new(p1)A(1);
  //析构函数可以显示调用
  p1->~A();
  operator delete(p1);
}

相关文章
|
14天前
|
存储 程序员 编译器
玩转C++内存管理:从新手到高手的必备指南
C++中的内存管理是编写高效、可靠程序的关键所在。C++不仅继承了C语言的内存管理方式,还增加了面向对象的内存分配机制,使得内存管理既有灵活性,也更加复杂。学习内存管理不仅有助于提升程序效率,还有助于理解计算机的工作原理和资源分配策略。
|
3月前
|
存储 缓存 编译器
【硬核】C++11并发:内存模型和原子类型
本文从C++11并发编程中的关键概念——内存模型与原子类型入手,结合详尽的代码示例,抽丝剥茧地介绍了如何实现无锁化并发的性能优化。
204 68
|
12天前
|
安全 C语言 C++
彻底摘明白 C++ 的动态内存分配原理
大家好,我是V哥。C++的动态内存分配允许程序在运行时请求和释放内存,主要通过`new`/`delete`(用于对象)及`malloc`/`calloc`/`realloc`/`free`(继承自C语言)实现。`new`分配并初始化对象内存,`delete`释放并调用析构函数;而`malloc`等函数仅处理裸内存,不涉及构造与析构。掌握这些可有效管理内存,避免泄漏和悬空指针问题。智能指针如`std::unique_ptr`和`std::shared_ptr`能自动管理内存,确保异常安全。关注威哥爱编程,了解更多全栈开发技巧。 先赞再看后评论,腰缠万贯财进门。
|
2月前
|
存储 程序员 编译器
什么是内存泄漏?C++中如何检测和解决?
大家好,我是V哥。内存泄露是编程中的常见问题,可能导致程序崩溃。特别是在金三银四跳槽季,面试官常问此问题。本文将探讨内存泄露的定义、危害、检测方法及解决策略,帮助你掌握这一关键知识点。通过学习如何正确管理内存、使用智能指针和RAII原则,避免内存泄露,提升代码健壮性。同时,了解常见的内存泄露场景,如忘记释放内存、异常处理不当等,确保在面试中不被秒杀。最后,预祝大家新的一年工作顺利,涨薪多多!关注威哥爱编程,一起成为更好的程序员。
|
4月前
|
存储 缓存 C语言
【c++】动态内存管理
本文介绍了C++中动态内存管理的新方式——`new`和`delete`操作符,详细探讨了它们的使用方法及与C语言中`malloc`/`free`的区别。文章首先回顾了C语言中的动态内存管理,接着通过代码实例展示了`new`和`delete`的基本用法,包括对内置类型和自定义类型的动态内存分配与释放。此外,文章还深入解析了`operator new`和`operator delete`的底层实现,以及定位new表达式的应用,最后总结了`malloc`/`free`与`new`/`delete`的主要差异。
88 3
|
4月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
280 4
|
5月前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
5月前
|
存储 C语言 C++
【C++打怪之路Lv6】-- 内存管理
【C++打怪之路Lv6】-- 内存管理
71 0
【C++打怪之路Lv6】-- 内存管理
|
5月前
|
C++
C/C++内存管理(下)
C/C++内存管理(下)
60 0
|
5月前
|
存储 Linux C语言
C/C++内存管理(上)
C/C++内存管理(上)
61 0