卓姆比尼人免安装绿色版
637M · 2025-09-26
C++程序在执行时,将内存大方向划分为4个区域
作用: 存储程序的二进制代码(即编译后的机器指令)。
特点: 1.只读,程序运行时不可修改。 2.由操作系统管理,程序结束时释放。
void func() {
// 函数代码存储在代码区
}
全局/静态区(Global/Static Segment)作用:
特点:1.在程序启动时分配,程序结束时释放。 2.未初始化的变量会被自动初始化为 0。
int globalVar = 10; // 已初始化全局变量,存储在全局区
static int staticVar; // 未初始化静态变量,存储在 BSS 段
void func() {
static int localStaticVar = 20; // 静态局部变量,存储在全局区
}
栈区(Stack Segment) 作用:存储局部变量、函数参数、函数返回地址等。
特点:
void func() {
int localVar = 30; // 局部变量,存储在栈区
}
堆区(Heap Segment) 作用: 存储动态分配的内存(如 new 和 malloc 分配的内存)。
特点:
void func() {
int* ptr = new int(40); // 动态分配内存,存储在堆区
delete ptr; // 手动释放内存
}
示例:
const char *str = "Hello, World!"; // 字符串常量存储在常量存储区
内存分区模型的特点
#include <iostream>
int globalVar = 10; // 全局变量,存储在全局区
static int staticVar; // 静态变量,存储在 BSS 段
void func() {
int localVar = 30; // 局部变量,存储在栈区
static int localStaticVar = 20; // 静态局部变量,存储在全局区
int* ptr = new int(40); // 动态分配内存,存储在堆区
std::cout << "Local Variable: " << localVar << std::endl;
std::cout << "Dynamic Memory: " << *ptr << std::endl;
delete ptr; // 释放堆区内存
}
int main() {
func();
return 0;
}
在 C++ 中,动态内存 是指在程序运行时(而不是编译时)从堆(Heap)中分配的内存。与栈上的自动内存管理不同,动态内存的分配和释放由程序员显式控制。
通过 new 和 delete 操作符(或 C 风格的 malloc 和 free)来分配和释放内存。
动态内存的使用场景包括:
运行时分配: 内存的分配和释放发生在程序运行时,而不是编译时。
手动管理: 程序员需要显式分配和释放内存,否则会导致内存泄漏。
堆区存储: 动态内存从堆区分配,堆区的空间通常比栈区大。
灵活性: 动态内存的大小可以在运行时动态调整,适合处理不确定大小的数据。
C++中利用==new==操作符在堆区开辟数据
堆区开辟的数据,由程序员手动开辟,手动释放,释放利用操作符 ==delete==
语法: new 数据类型
利用new创建的数据,会返回该数据对应的类型的指针
分配单个对象:
class MyClass {
public:
MyClass() {
std::cout << "MyClass constructor called" << std::endl;
}
MyClass(int age, string name) {
this->age = age;
this->name = name;
std::cout << "MyClass constructor " << this->age << " , " << this->name << std::endl;
}
~MyClass() {
std::cout << "MyClass destructor called" << std::endl;
}
public:
int age;
string name;
};
void test1() {
// 使用new运算符创建MyClass对象
MyClass* obj = new MyClass();
// 使用对象指针调用对象的成员函数
// ...
// 释放动态分配的内存
delete obj;
}
void test2() {
MyClass* obj = new MyClass(30,"yc");
delete obj;
}
int main() {
// test1();
test2();
return 0;
}
手动管理动态数组
//堆区开辟数组
void test() {
int* arr = new int[10];
for (int i = 0; i < 10; i++) {
arr[i] = i+ 100;
}
for (int i = 0; i < 10; i++) {
cout << arr[i] << endl;
}
delete[] arr;
}
int main() {
test();
return 0;
}
动态数组,C++ 提供了 std::vector
作为动态数组的替代方案,避免手动管理内存。
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3}; // 动态数组
vec.push_back(4); // 添加元素
for (int i : vec) {
std::cout << i << " "; // 输出: 1 2 3 4
}
return 0;
}
释放单个对象:
delete ptr; // 释放单个对象
ptr = nullptr; // 将指针置为 nullptr,避免野指针
释放数组:
delete[] arr; // 释放数组
arr = nullptr; // 将指针置为 nullptr
动态数组
#include <iostream>
int main() {
int size = 5;
int* arr = new int[size]; // 动态分配数组
for (int i = 0; i < size; i++) {
arr[i] = i * 2; // 初始化数组
}
for (int i = 0; i < size; i++) {
std::cout << arr[i] << " "; // 输出数组
}
delete[] arr; // 释放数组内存
return 0;
}
动态对象
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "Constructor called!n"; }
~MyClass() { std::cout << "Destructor called!n"; }
void print() { std::cout << "Hello, World!n"; }
};
int main() {
MyClass* obj = new MyClass; // 动态分配对象
obj->print();
delete obj; // 释放对象内存
return 0;
}
std::unique_ptr
或 std::shared_ptr
。std::vector
、std::list
等,避免手动管理动态数组。nullptr
。new
都有对应的 delete
,或使用智能指针。如果动态分配的内存没有被释放,会导致内存泄漏。解决方法:确保每次 new 都有对应的 delete。
int* ptr = new int;
// 忘记调用 delete ptr;
未初始化的指针称为野指针,访问野指针会导致未定义行为。解决方法:始终初始化指针。
int* ptr; // 未初始化
*ptr = 10; // 未定义行为
释放内存后,指针仍然指向已释放的内存地址,称为悬空指针。解决方法:释放内存后将指针置为 nullptr。
int* ptr = new int;
delete ptr;
*ptr = 10; // 未定义行为,可能导致崩溃
C++11 引入了智能指针,用于自动管理动态内存,避免内存泄漏和悬空指针。
std::unique_ptr
:独占所有权的智能指针。std::shared_ptr
:共享所有权的智能指针。std::weak_ptr
:弱引用,不增加引用计数。示例:
#include <memory>
int main() {
std::unique_ptr<int> ptr(new int(10)); // 分配内存
std::cout << *ptr << std::endl; // 输出: 10
// 不需要手动释放内存
return 0;
}
示例:
#include <memory>
int main() {
std::shared_ptr<int> ptr1 = std::make_shared<int>(20); // 分配内存
std::shared_ptr<int> ptr2 = ptr1; // 共享所有权
std::cout << *ptr1 << " " << *ptr2 << std::endl; // 输出: 20 20
// 不需要手动释放内存
return 0;
}
std::shared_ptr
的循环引用问题。示例:
#include <memory>
int main() {
std::shared_ptr<int> sharedPtr = std::make_shared<int>(30);
std::weak_ptr<int> weakPtr = sharedPtr; // 弱引用
if (auto spt = weakPtr.lock()) { // 尝试提升为 shared_ptr
std::cout << *spt << std::endl; // 输出: 30
}
return 0;
}
C++ 提供了底层内存管理函数,如 malloc
、free
、calloc
和 realloc
,但通常不推荐使用。
malloc
和 free
#include <cstdlib>
int main() {
int *p = (int *)malloc(sizeof(int)); // 分配内存
*p = 10;
std::cout << *p << std::endl; // 输出: 10
free(p); // 释放内存
return 0;
}
calloc
和 realloc
#include <cstdlib>
int main() {
int *arr = (int *)calloc(3, sizeof(int)); // 分配并初始化内存
arr[0] = 1;
arr = (int *)realloc(arr, 5 * sizeof(int)); // 重新分配内存
arr[3] = 4;
for (int i = 0; i < 5; ++i) {
std::cout << arr[i] << " "; // 输出: 1 0 0 4 0
}
free(arr); // 释放内存
return 0;
}
内存对齐是指数据在内存中的起始地址必须是某个值的整数倍。对齐可以提高内存访问效率。
int
对齐到 4 字节)。示例:
struct alignas(16) MyStruct {
int a; // 4 字节
double b; // 8 字节
}; // 结构体对齐到 16 字节
使用 alignof
查看类型的对齐值。
std::cout << alignof(int) << std::endl; // 输出: 4
腾讯 QQ 音乐推出“网赚畅听包”会员,付费后每天看广告获取听歌权益
开源电子书管家 Calibre 8.11 发布:整合 AI 问答功能,随时解答你的提问