第11章 内存与资源管理
内存管理基础
内存区域
C++程序运行时,内存通常分为以下几个区域,每个区域都有其特定的用途和管理方式:
- 代码区(Text Segment):存储程序的可执行机器代码,通常是只读的,以防止程序意外修改自身指令
- 只读数据区(RODATA):存储字符串字面量和其他常量,同样是只读的
- 全局/静态区(Data Segment):存储初始化的全局变量和静态变量,程序启动时分配,结束时释放
- 未初始化数据区(BSS Segment):存储未初始化的全局变量和静态变量,程序启动时会被自动初始化为0
- 堆区(Heap):动态分配的内存,由程序员通过
new/delete或malloc/free管理,分配和释放的顺序可以任意 - 栈区(Stack):存储函数调用时的局部变量、函数参数和返回地址,由编译器自动管理,遵循后进先出(LIFO)原则
内存布局示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 高地址 ┌─────────────────────────────────┐ │ 栈区 (Stack) │ ← 向下增长 ├─────────────────────────────────┤ │ 堆区 (Heap) │ ← 向上增长 ├─────────────────────────────────┤ │ 未初始化数据区 (BSS Segment) │ ├─────────────────────────────────┤ │ 初始化数据区 (Data Segment) │ ├─────────────────────────────────┤ │ 只读数据区 (RODATA) │ ├─────────────────────────────────┤ │ 代码区 (Text Segment) │ └─────────────────────────────────┘ 低地址
|
内存分配方式
C++中有三种基本内存分配方式,每种方式都有其特定的适用场景和性能特点:
静态分配:编译时由编译器分配,如全局变量、静态变量
- 优点:分配速度快,无需运行时开销
- 缺点:生命周期固定,无法在运行时调整大小
- 适用场景:存储程序运行期间始终需要的数据,如配置参数、全局状态
栈分配:函数调用时由编译器自动分配,函数返回时自动释放
- 优点:分配和释放速度极快,仅需修改栈指针
- 缺点:空间有限,生命周期受限
- 适用场景:存储函数局部变量和参数,生命周期与函数调用一致
堆分配:运行时通过内存分配器手动分配,需要手动释放
- 优点:空间较大,生命周期灵活
- 缺点:分配和释放速度较慢,需要手动管理
- 适用场景:存储大小不确定或生命周期与函数调用无关的数据
性能比较:
- 分配速度:栈分配 > 静态分配 > 堆分配
- 空间大小:堆分配 > 静态分配 > 栈分配
- 灵活性:堆分配 > 静态分配 > 栈分配
内存分配的底层实现:
- 栈分配:通过修改栈指针(ESP/RSP寄存器)实现,分配时栈指针减少,释放时栈指针增加
- 堆分配:通过内存分配器(如ptmalloc、tcmalloc、jemalloc)管理,维护空闲内存块链表,分配时查找合适大小的块,释放时将块放回链表
- 静态分配:在程序加载时由操作系统加载器分配,位于数据段或BSS段
动态内存分配
new和delete运算符
C++使用new和delete运算符进行动态内存分配和释放,它们在C的malloc/free基础上增加了对象的构造和析构功能。
基本用法
1 2 3 4 5 6 7 8 9 10 11 12
| int* p = new int; *p = 42; std::cout << *p << std::endl; delete p;
int* arr = new int[10]; for (int i = 0; i < 10; ++i) { arr[i] = i; } delete[] arr;
|
初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| int* p1 = new int(100);
int* arr1 = new int[5]{1, 2, 3, 4, 5};
int* p2 = new int{};
int* arr2 = new int[5]{};
class Point { public: Point(int x, int y) : x(x), y(y) {} int x, y; };
Point* p3 = new Point{10, 20}; delete p3;
|
定位new
定位new(Placement New)允许在指定的内存位置创建对象,而不分配新的内存:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <new>
char buffer[sizeof(int)];
int* p = new (buffer) int(42);
std::cout << *p << std::endl;
|
定位new的高级应用:
- 内存池:预分配大块内存,然后在其中构造对象
- 自定义分配器:实现特定的内存分配策略
- 对象重用:在同一内存位置重复构造不同类型的对象
new和delete的底层实现
new运算符的工作过程:
- 调用
operator new分配原始内存 - 在分配的内存上调用构造函数
- 返回指向新对象的指针
delete运算符的工作过程:
- 调用对象的析构函数
- 调用
operator delete释放内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| T* new_T() { void* memory = operator new(sizeof(T)); try { new (memory) T(); return static_cast<T*>(memory); } catch (...) { operator delete(memory); throw; } }
void delete_T(T* ptr) { if (ptr) { ptr->~T(); operator delete(ptr); } }
|
重载new和delete运算符
C++允许重载new和delete运算符,以实现自定义的内存分配策略:
- 全局重载:影响整个程序的内存分配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void* operator new(size_t size) { std::cout << "Custom new called for size " << size << std::endl; void* p = std::malloc(size); if (!p) { throw std::bad_alloc{}; } return p; }
void operator delete(void* p) noexcept { std::cout << "Custom delete called" << std::endl; std::free(p); }
|
- 类级重载:仅影响特定类的对象分配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class MyClass { public: void* operator new(size_t size) { std::cout << "MyClass new called for size " << size << std::endl; void* p = std::malloc(size); if (!p) { throw std::bad_alloc{}; } return p; } void operator delete(void* p) noexcept { std::cout << "MyClass delete called" << std::endl; std::free(p); } void* operator new[](size_t size) { std::cout << "MyClass new[] called for size " << size << std::endl; void* p = std::malloc(size); if (!p) { throw std::bad_alloc{}; } return p; } void operator delete[](void* p) noexcept { std::cout << "MyClass delete[] called" << std::endl; std::free(p); } };
|
- 放置版本重载:自定义定位new的行为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| void* operator new(size_t size, const char* file, int line) { std::cout << "Placement new called from " << file << ":" << line << std::endl; return operator new(size); }
void operator delete(void* p, const char* file, int line) noexcept { std::cout << "Placement delete called from " << file << ":" << line << std::endl; operator delete(p); }
#define DEBUG_NEW new(__FILE__, __LINE__) MyClass* p = DEBUG_NEW MyClass(); delete p;
|
内存分配策略
- 内存池:预分配大块内存,然后将其分割成小块进行分配,减少内存碎片
- 对象池:为特定类型的对象预分配内存,避免频繁的构造和析构
- 区域分配器:为特定生命周期的对象分配内存,一次性释放整个区域
- 缓存分配器:缓存最近释放的内存块,以加速后续的分配请求
内存池示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| class MemoryPool { public: MemoryPool(size_t blockSize, size_t blockCount) : blockSize(blockSize), blockCount(blockCount) { pool = static_cast<char*>(std::malloc(blockSize * blockCount)); if (!pool) { throw std::bad_alloc{}; } for (size_t i = 0; i < blockCount; ++i) { char* block = pool + i * blockSize; *reinterpret_cast<char**>(block) = freeList; freeList = block; } } ~MemoryPool() { std::free(pool); } void* allocate() { if (!freeList) { throw std::bad_alloc{}; } void* block = freeList; freeList = *reinterpret_cast<char**>(freeList); return block; } void deallocate(void* ptr) { if (!ptr) return; *reinterpret_cast<char**>(ptr) = freeList; freeList = static_cast<char*>(ptr); } private: size_t blockSize; size_t blockCount; char* pool; char* freeList; };
MemoryPool pool(sizeof(int), 100); int* p = static_cast<int*>(pool.allocate()); *p = 42; pool.deallocate(p);
|
智能指针
C++11引入了智能指针,用于自动管理动态内存,避免内存泄漏。智能指针通过RAII(资源获取即初始化)机制,在对象生命周期结束时自动释放所管理的资源。
std::unique_ptr
std::unique_ptr是一种独占所有权的智能指针,同一时间只能有一个unique_ptr指向同一个对象,所有权可以转移但不能复制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <memory>
std::unique_ptr<int> p1(new int(42));
auto p2 = std::make_unique<int>(100);
std::unique_ptr<int> p3 = std::move(p1);
std::cout << *p2 << std::endl; std::cout << *p3 << std::endl;
if (p1) { std::cout << *p1 << std::endl; } else { std::cout << "p1 is null" << std::endl; }
p2.reset();
p3.reset(new int(200));
int* rawPtr = p3.get();
|
std::unique_ptr的性能优势:
- 大小与原始指针相同(通常为8字节)
- 无引用计数开销
- 移动操作开销极小
- 适用于大多数需要独占所有权的场景
std::unique_ptr与数组:
1 2 3 4 5 6 7 8 9
| std::unique_ptr<int[]> arr(new int[10]); for (int i = 0; i < 10; ++i) { arr[i] = i; }
auto arr2 = std::make_unique<int[]>(10);
|
std::shared_ptr
std::shared_ptr是一种共享所有权的智能指针,多个shared_ptr可以指向同一个对象,使用引用计数来管理内存。当最后一个shared_ptr被销毁时,对象才会被释放。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <memory>
std::shared_ptr<int> p1(new int(42));
auto p2 = std::make_shared<int>(100);
std::shared_ptr<int> p3 = p1;
std::cout << *p1 << std::endl; std::cout << *p2 << std::endl; std::cout << *p3 << std::endl;
std::cout << "p1 use_count: " << p1.use_count() << std::endl;
p1.reset(); std::cout << "p3 use_count after p1.reset(): " << p3.use_count() << std::endl;
|
std::shared_ptr的内部实现:
- 控制块:存储引用计数、弱引用计数和自定义删除器
- 内存布局:当使用
make_shared时,控制块和对象在同一块内存中分配,减少内存开销
std::shared_ptr的性能考虑:
- 大小为两个指针(通常为16字节)
- 引用计数操作是原子的,有一定的线程安全开销
- 避免使用
shared_ptr(new T()),优先使用make_shared<T>()
std::weak_ptr
std::weak_ptr是一种不增加引用计数的智能指针,用于解决shared_ptr的循环引用问题,也可以用于观察对象是否存在。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <memory>
class B;
class A { public: std::shared_ptr<B> b; ~A() { std::cout << "A destroyed" << std::endl; } };
class B { public: std::weak_ptr<A> a; ~B() { std::cout << "B destroyed" << std::endl; } };
int main() { auto a = std::make_shared<A>(); auto b = std::make_shared<B>(); a->b = b; b->a = a; std::cout << "a use_count: " << a.use_count() << std::endl; std::cout << "b use_count: " << b.use_count() << std::endl; if (auto locked = b->a.lock()) { std::cout << "A still exists" << std::endl; } else { std::cout << "A has been destroyed" << std::endl; } return 0; }
|
std::weak_ptr的应用场景:
- 解决循环引用问题
- 观察者模式:观察者持有被观察对象的弱引用
- 缓存:缓存对象的弱引用,避免缓存导致对象无法释放
自定义删除器
智能指针支持自定义删除器,用于处理特殊的资源释放逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <memory> #include <fstream>
struct FileDeleter { void operator()(std::FILE* fp) { if (fp) { std::fclose(fp); std::cout << "File closed" << std::endl; } } };
std::unique_ptr<std::FILE, FileDeleter> filePtr(std::fopen("test.txt", "w"));
auto deleter = [](int* p) { std::cout << "Custom deleter called" << std::endl; delete p; };
std::unique_ptr<int, decltype(deleter)> p(new int(42), deleter);
std::shared_ptr<int> sp(new int(100), [](int* p) { std::cout << "Shared deleter called" << std::endl; delete p; });
std::shared_ptr<int> arrSp(new int[10], [](int* p) { delete[] p; });
|
自定义删除器的应用场景:
- 管理非堆内存资源(如文件句柄、网络连接、数据库连接)
- 实现特殊的资源释放逻辑(如解锁互斥锁、通知其他线程)
- 与第三方库集成,使用库特定的释放函数
智能指针的实现原理
std::unique_ptr的简化实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| template<typename T, typename Deleter = std::default_delete<T>> class UniquePtr { public: explicit UniquePtr(T* ptr = nullptr) : ptr_(ptr) {} ~UniquePtr() { if (ptr_) { deleter_(ptr_); } } UniquePtr(const UniquePtr&) = delete; UniquePtr& operator=(const UniquePtr&) = delete; UniquePtr(UniquePtr&& other) noexcept : ptr_(other.ptr_) { other.ptr_ = nullptr; } UniquePtr& operator=(UniquePtr&& other) noexcept { if (this != &other) { if (ptr_) { deleter_(ptr_); } ptr_ = other.ptr_; other.ptr_ = nullptr; } return *this; } T& operator*() const { return *ptr_; } T* operator->() const { return ptr_; } T* get() const { return ptr_; } void reset(T* ptr = nullptr) { if (ptr_) { deleter_(ptr_); } ptr_ = ptr; } T* release() { T* tmp = ptr_; ptr_ = nullptr; return tmp; } explicit operator bool() const { return ptr_ != nullptr; } private: T* ptr_; Deleter deleter_; };
|
std::shared_ptr的简化实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| template<typename T> class SharedPtr { public: explicit SharedPtr(T* ptr = nullptr) : ptr_(ptr) { if (ptr_) { controlBlock_ = new ControlBlock(ptr_); } } SharedPtr(const SharedPtr& other) : ptr_(other.ptr_), controlBlock_(other.controlBlock_) { if (controlBlock_) { controlBlock_->increment(); } } ~SharedPtr() { if (controlBlock_) { if (controlBlock_->decrement() == 0) { delete controlBlock_; } } } SharedPtr& operator=(const SharedPtr& other) { if (this != &other) { if (controlBlock_) { if (controlBlock_->decrement() == 0) { delete controlBlock_; } } ptr_ = other.ptr_; controlBlock_ = other.controlBlock_; if (controlBlock_) { controlBlock_->increment(); } } return *this; } T& operator*() const { return *ptr_; } T* operator->() const { return ptr_; } T* get() const { return ptr_; } long use_count() const { return controlBlock_ ? controlBlock_->count() : 0; } private: struct ControlBlock { ControlBlock(T* ptr) : ptr(ptr), refCount(1) {} ~ControlBlock() { delete ptr; } void increment() { refCount++; } long decrement() { return --refCount; } long count() const { return refCount; } T* ptr; long refCount; }; T* ptr_; ControlBlock* controlBlock_; };
|
智能指针与多线程
std::shared_ptr的线程安全性:
- 引用计数的操作是线程安全的(原子操作)
- 多个线程可以同时读取和修改同一个
shared_ptr的引用计数 - 但对
shared_ptr所管理对象的访问不是线程安全的,需要额外的同步措施
std::unique_ptr的线程安全性:
- 不提供线程安全保证
- 同一时间只能有一个线程访问同一个
unique_ptr - 可以通过移动语义在不同线程间传递所有权
多线程环境下的智能指针使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include <memory> #include <thread> #include <mutex>
std::shared_ptr<int> sharedData = std::make_shared<int>(42); std::mutex dataMutex;
void threadFunction() { { std::lock_guard<std::mutex> lock(dataMutex); std::cout << "Thread read: " << *sharedData << std::endl; } { std::lock_guard<std::mutex> lock(dataMutex); *sharedData = 100; std::cout << "Thread modified: " << *sharedData << std::endl; } }
int main() { std::thread t1(threadFunction); std::thread t2(threadFunction); t1.join(); t2.join(); return 0; }
|
RAII
RAII的概念
RAII(Resource Acquisition Is Initialization)是一种C++编程技术,用于资源管理。它的核心思想是:
- 资源获取时初始化:在构造函数中获取资源
- 资源在对象生命周期内保持有效:对象存在时,资源有效
- 资源在对象销毁时释放:在析构函数中释放资源
RAII的应用
RAII常用于管理以下资源:
- 内存:使用智能指针
- 文件句柄:使用RAII包装器
- 网络连接:使用RAII包装器
- 互斥锁:使用
std::lock_guard等
自定义RAII类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| class FileHandler { public: FileHandler(const char* filename, const char* mode) { file = fopen(filename, mode); if (!file) { throw std::runtime_error("Failed to open file"); } } ~FileHandler() { if (file) { fclose(file); } } FileHandler(const FileHandler&) = delete; FileHandler& operator=(const FileHandler&) = delete; FILE* get() const { return file; } void write(const char* data) { if (file) { fprintf(file, "%s", data); } } private: FILE* file; };
void useFile() { FileHandler file("test.txt", "w"); file.write("Hello, RAII!"); }
|
资源管理工具
标准库中的RAII工具
std::lock_guard
std::lock_guard是一个互斥锁的RAII包装器,在构造时锁定互斥锁,在析构时解锁。
1 2 3 4 5 6 7 8 9
| #include <mutex>
std::mutex mtx;
void criticalSection() { std::lock_guard<std::mutex> lock(mtx); }
|
std::unique_lock
std::unique_lock是一个更灵活的互斥锁RAII包装器,支持延迟锁定、超时锁定等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <mutex> #include <chrono>
std::mutex mtx;
void tryLock() { std::unique_lock<std::mutex> lock(mtx, std::defer_lock); if (lock.try_lock()) { } if (lock.try_lock_for(std::chrono::seconds(1))) { } }
|
std::scoped_lock
C++17引入的std::scoped_lock可以同时锁定多个互斥锁,避免死锁。
1 2 3 4 5 6 7 8
| #include <mutex>
std::mutex mtx1, mtx2;
void lockMultiple() { std::scoped_lock lock(mtx1, mtx2); }
|
内存管理最佳实践
1. 优先使用智能指针
尽量使用std::unique_ptr和std::shared_ptr代替原始指针,避免内存泄漏。
2. 使用std::make_unique和std::make_shared
使用std::make_unique和std::make_shared创建智能指针,避免异常安全问题。
3. 避免循环引用
使用std::weak_ptr解决std::shared_ptr的循环引用问题。
4. 合理使用RAII
为所有资源创建RAII包装器,确保资源的正确释放。
5. 避免内存泄漏
- 总是配对使用
new和delete - 优先使用智能指针
- 使用RAII管理资源
6. 避免悬空指针
- 释放内存后将指针置为
nullptr - 使用智能指针自动管理指针生命周期
7. 避免野指针
内存优化
内存分配策略
- 减少动态内存分配:优先使用栈分配和静态分配
- 批量分配:使用
std::vector等容器,避免频繁的小内存分配 - 内存池:对于频繁分配和释放的小对象,使用内存池
- 多态内存资源(C++17+):使用
std::pmr命名空间中的内存资源管理工具
内存对齐
内存对齐可以提高内存访问速度,C++11引入了alignas和alignof关键字来控制内存对齐。
C++20新特性:std::span
std::span是C++20引入的一个非拥有式视图,用于表示连续内存区域的序列,避免不必要的内存拷贝:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <span> #include <vector>
void processArray(std::span<int> data) { for (auto& element : data) { element *= 2; } }
int main() { int arr[] = {1, 2, 3, 4, 5}; processArray(arr); std::vector<int> vec = {6, 7, 8, 9, 10}; processArray(vec); processArray(std::span(vec).subspan(1, 3)); return 0; }
|
C++17新特性:多态内存资源
C++17引入了std::pmr命名空间,提供了多态内存资源管理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <memory_resource> #include <vector>
int main() { char buffer[1024]; std::pmr::monotonic_buffer_resource pool(buffer, sizeof(buffer)); std::pmr::vector<int> vec(&pool); for (int i = 0; i < 100; ++i) { vec.push_back(i); } return 0; }
|
1 2 3 4 5 6 7 8 9 10 11
| alignas(16) int x;
std::cout << "alignof(int): " << alignof(int) << std::endl;
struct alignas(32) MyStruct { int a; double b; };
|
内存使用分析
使用工具分析内存使用情况,找出内存泄漏和内存使用效率低下的地方。
- Valgrind:Linux下的内存分析工具
- AddressSanitizer:Google开发的内存错误检测工具
- Visual Studio Memory Profiler:Windows下的内存分析工具
示例:内存管理的综合应用
自定义智能指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| template<typename T> class SmartPtr { public: explicit SmartPtr(T* ptr = nullptr) : ptr(ptr) {} ~SmartPtr() { delete ptr; } SmartPtr(const SmartPtr&) = delete; SmartPtr& operator=(const SmartPtr&) = delete; SmartPtr(SmartPtr&& other) noexcept : ptr(other.ptr) { other.ptr = nullptr; } SmartPtr& operator=(SmartPtr&& other) noexcept { if (this != &other) { delete ptr; ptr = other.ptr; other.ptr = nullptr; } return *this; } T& operator*() const { return *ptr; } T* operator->() const { return ptr; } explicit operator bool() const { return ptr != nullptr; } private: T* ptr; };
void useSmartPtr() { SmartPtr<int> p(new int(42)); std::cout << *p << std::endl; SmartPtr<int> p2 = std::move(p); std::cout << *p2 << std::endl; }
|
资源管理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| class DatabaseConnection { public: DatabaseConnection(const std::string& connectionString) { std::cout << "Connecting to database: " << connectionString << std::endl; connected = true; } ~DatabaseConnection() { if (connected) { std::cout << "Disconnecting from database" << std::endl; connected = false; } } DatabaseConnection(const DatabaseConnection&) = delete; DatabaseConnection& operator=(const DatabaseConnection&) = delete; DatabaseConnection(DatabaseConnection&& other) noexcept : connected(other.connected) { other.connected = false; } DatabaseConnection& operator=(DatabaseConnection&& other) noexcept { if (this != &other) { if (connected) { std::cout << "Disconnecting from database" << std::endl; } connected = other.connected; other.connected = false; } return *this; } void executeQuery(const std::string& query) { if (connected) { std::cout << "Executing query: " << query << std::endl; } else { throw std::runtime_error("Not connected to database"); } } private: bool connected; };
void useDatabase() { try { DatabaseConnection db("server=localhost;database=test"); db.executeQuery("SELECT * FROM users"); } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; } }
|
总结
内存与资源管理是C++编程中的重要主题,直接关系到程序的性能和稳定性。通过合理使用动态内存分配、智能指针和RAII等技术,可以有效地管理内存和资源,避免内存泄漏、悬空指针等问题。
在现代C++中,应该优先使用智能指针和RAII来管理内存和资源,减少手动内存管理的错误。同时,合理的内存分配策略和内存优化技术可以提高程序的性能和内存使用效率。
通过本章的学习,读者应该掌握C++中的内存管理和资源管理技术,能够编写更加安全、高效的C++程序。