🏗️ C++基础语法与内存管理深度指南
一、C++基础语法核心要点
1.1 C++基础语法速览
1.1.1 基本程序结构
cpp
// 标准C++程序模板
#include <iostream> // 输入输出流
#include <string> // 字符串类
using namespace std; // 使用std命名空间(慎用)
int main() { // 主函数
// 基本输出
cout << "Hello, C++!" << endl;
// 变量声明与初始化
int age = 25; // 传统初始化
double price {99.99}; // C++11统一初始化
auto name = "Alice"s; // C++14自动类型推导
// 常量
const int MAX_SIZE = 100;
constexpr double PI = 3.14159; // 编译时常量
// 引用(别名)
int& refAge = age; // refAge是age的别名
refAge = 30; // 同时修改了age
// 指针
int* ptr = &age; // ptr指向age的地址
*ptr = 35; // 通过指针修改值
return 0; // 程序正常退出
}
1.1.2 现代C++类型系统
cpp
#include <iostream>
#include <typeinfo>
#include <vector>
int main() {
// 1. 基本类型
bool flag = true; // 布尔型(1字节)
char ch = 'A'; // 字符型(1字节)
wchar_t wch = L'字'; // 宽字符
char16_t c16 = u'字'; // UTF-16字符(C++11)
char32_t c32 = U'字'; // UTF-32字符(C++11)
// 2. 整型(带符号)
short s = 100; // 短整型(通常2字节)
int i = 1000; // 整型(通常4字节)
long l = 10000L; // 长整型
long long ll = 100000LL; // 长长整型(C++11)
// 3. 浮点型
float f = 3.14f; // 单精度浮点(4字节)
double d = 3.1415926535; // 双精度浮点(8字节)
long double ld = 3.141592653589793238L; // 扩展精度
// 4. 类型推导(C++11起)
auto x = 42; // x的类型是int
auto y = 3.14; // y的类型是double
auto z = "Hello"; // z的类型是const char*
// decltype获取表达式类型
decltype(x) copyX = x; // copyX的类型是int
decltype((x)) refX = x; // refX的类型是int&
// 5. 类型别名(更易读)
using String = std::string; // C++11方式
typedef std::vector<int> IntVec; // 传统方式
return 0;
}
1.2 函数进阶特性
cpp
#include <iostream>
#include <functional>
// 1. 函数重载(Overloading)
void print(int value) {
cout << "整数: " << value << endl;
}
void print(double value) {
cout << "浮点数: " << value << endl;
}
void print(const std::string& value) {
cout << "字符串: " << value << endl;
}
// 2. 默认参数
void setup(int width = 800, int height = 600, bool fullscreen = false) {
cout << "分辨率: " << width << "x" << height
<< ", 全屏: " << fullscreen << endl;
}
// 3. 内联函数(减少函数调用开销)
inline int square(int x) {
return x * x;
}
// 4. 常量表达式函数(C++11)
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
// 5. Lambda表达式(C++11)
auto lambdaExample() {
// 基本lambda
auto add = [](int a, int b) { return a + b; };
// 捕获列表
int multiplier = 3;
auto times = [multiplier](int x) { return x * multiplier; };
// 通用lambda(C++14)
auto generic = [](auto a, auto b) { return a + b; };
return add(5, 3); // 返回8
}
// 6. 函数指针和std::function
void demoFunctionTypes() {
// 函数指针
int (*funcPtr)(int, int) = nullptr;
funcPtr = [](int a, int b) { return a * b; };
// std::function(更安全灵活)
std::function<int(int, int)> func;
func = [](int a, int b) { return a + b; };
// 绑定参数
auto addFive = std::bind(func, std::placeholders::_1, 5);
cout << addFive(10) << endl; // 输出15
}
int main() {
print(42); // 调用print(int)
print(3.14); // 调用print(double)
print("Hello"); // 调用print(const string&)
setup(); // 使用所有默认参数
setup(1024); // 只提供width
setup(1920, 1080, true);// 提供所有参数
cout << "5的平方: " << square(5) << endl;
cout << "5的阶乘: " << factorial(5) << endl;
return 0;
}
二、面向对象编程深入
2.1 类与对象
cpp
#include <iostream>
#include <string>
// 1. 基本类定义
class Person {
private: // 私有成员,类外不可访问
std::string name;
int age;
protected: // 保护成员,派生类可访问
std::string id;
public: // 公有成员,类外可访问
// 构造函数
Person() : name("Unknown"), age(0), id("0000") {
std::cout << "默认构造函数" << std::endl;
}
Person(const std::string& n, int a) : name(n), age(a) {
id = generateId();
}
// 拷贝构造函数
Person(const Person& other) : name(other.name), age(other.age), id(other.id) {
std::cout << "拷贝构造函数" << std::endl;
}
// 移动构造函数(C++11)
Person(Person&& other) noexcept
: name(std::move(other.name)),
age(other.age),
id(std::move(other.id)) {
other.age = 0;
std::cout << "移动构造函数" << std::endl;
}
// 析构函数
~Person() {
std::cout << "析构函数: " << name << std::endl;
}
// 成员函数
void introduce() const {
std::cout << "我叫" << name << ", 今年" << age << "岁" << std::endl;
}
// 设置器和获取器
void setName(const std::string& newName) { name = newName; }
const std::string& getName() const { return name; }
// 静态成员
static int population;
static std::string generateId() {
return "ID_" + std::to_string(++population);
}
// 友元函数
friend void printPrivateInfo(const Person& p);
// 运算符重载
Person& operator=(const Person& other) {
if (this != &other) {
name = other.name;
age = other.age;
id = other.id;
}
return *this;
}
bool operator==(const Person& other) const {
return name == other.name && age == other.age;
}
};
// 静态成员初始化
int Person::population = 0;
// 友元函数实现
void printPrivateInfo(const Person& p) {
std::cout << "私有信息: " << p.name << ", " << p.age << std::endl;
}
// 2. 继承
class Student : public Person {
private:
std::string studentId;
double gpa;
public:
// 使用基类构造函数
using Person::Person;
Student(const std::string& n, int a, const std::string& sid, double g)
: Person(n, a), studentId(sid), gpa(g) {}
void study() {
std::cout << getName() << "正在学习" << std::endl;
}
// 重写基类函数
void introduce() const {
Person::introduce(); // 调用基类版本
std::cout << "我是学生,学号: " << studentId << std::endl;
}
};
// 3. 多态与虚函数
class Animal {
public:
// 虚函数
virtual void speak() const {
std::cout << "动物叫" << std::endl;
}
// 纯虚函数(抽象类)
virtual void move() const = 0;
// 虚析构函数(重要!)
virtual ~Animal() {
std::cout << "Animal析构" << std::endl;
}
};
class Dog : public Animal {
public:
void speak() const override {
std::cout << "汪汪!" << std::endl;
}
void move() const override {
std::cout << "用四条腿跑" << std::endl;
}
~Dog() override {
std::cout << "Dog析构" << std::endl;
}
};
class Bird : public Animal {
public:
void speak() const override final { // final防止进一步重写
std::cout << "叽叽喳喳" << std::endl;
}
void move() const override {
std::cout << "用翅膀飞" << std::endl;
}
};
int main() {
// 对象创建
Person p1("张三", 25);
Person p2 = p1; // 拷贝构造
Person p3 = std::move(p1); // 移动构造
// 多态演示
Animal* animals[2];
animals[0] = new Dog();
animals[1] = new Bird();
for (int i = 0; i < 2; i++) {
animals[i]->speak(); // 动态绑定
animals[i]->move();
delete animals[i]; // 正确调用派生类析构函数
}
return 0;
}
2.2 现代C++特性:智能指针
cpp
#include <memory>
#include <iostream>
class Resource {
public:
Resource() { std::cout << "Resource创建" << std::endl; }
~Resource() { std::cout << "Resource销毁" << std::endl; }
void use() { std::cout << "使用Resource" << std::endl; }
};
void demoSmartPointers() {
std::cout << "\n=== 智能指针演示 ===" << std::endl;
// 1. unique_ptr(独占所有权)
{
std::cout << "\n1. unique_ptr演示:" << std::endl;
std::unique_ptr<Resource> up1(new Resource());
auto up2 = std::make_unique<Resource>(); // 推荐方式(C++14)
// 所有权转移
std::unique_ptr<Resource> up3 = std::move(up1);
// 自定义删除器
auto deleter = [](Resource* ptr) {
std::cout << "自定义删除器" << std::endl;
delete ptr;
};
std::unique_ptr<Resource, decltype(deleter)> up4(new Resource(), deleter);
}
// 2. shared_ptr(共享所有权)
{
std::cout << "\n2. shared_ptr演示:" << std::endl;
std::shared_ptr<Resource> sp1 = std::make_shared<Resource>();
std::cout << "引用计数: " << sp1.use_count() << std::endl;
{
std::shared_ptr<Resource> sp2 = sp1;
std::cout << "引用计数: " << sp1.use_count() << std::endl;
std::shared_ptr<Resource> sp3 = sp2;
std::cout << "引用计数: " << sp1.use_count() << std::endl;
}
std::cout << "引用计数: " << sp1.use_count() << std::endl;
// 循环引用问题
struct Node {
std::shared_ptr<Node> next;
~Node() { std::cout << "Node销毁" << std::endl; }
};
auto node1 = std::make_shared<Node>();
auto node2 = std::make_shared<Node>();
node1->next = node2;
node2->next = node1; // 循环引用!内存泄漏
}
// 3. weak_ptr(弱引用)
{
std::cout << "\n3. weak_ptr演示:" << std::endl;
std::shared_ptr<Resource> sp = std::make_shared<Resource>();
std::weak_ptr<Resource> wp = sp;
std::cout << "引用计数: " << sp.use_count() << std::endl;
std::cout << "weak_ptr是否过期: " << wp.expired() << std::endl;
if (auto locked = wp.lock()) {
locked->use();
std::cout << "成功获取shared_ptr" << std::endl;
}
sp.reset(); // 释放资源
std::cout << "weak_ptr是否过期: " << wp.expired() << std::endl;
// 解决循环引用
struct SafeNode {
std::weak_ptr<SafeNode> next; // 使用weak_ptr
~SafeNode() { std::cout << "SafeNode销毁" << std::endl; }
};
auto safeNode1 = std::make_shared<SafeNode>();
auto safeNode2 = std::make_shared<SafeNode>();
safeNode1->next = safeNode2;
safeNode2->next = safeNode1; // 不会造成内存泄漏
}
}
int main() {
demoSmartPointers();
return 0;
}
三、C++内存管理深度解析
3.1 内存分区模型
cpp
#include <iostream>
#include <string>
// 全局变量 - 数据段
int globalVar = 100; // 初始化的全局变量(.data段)
int uninitGlobalVar; // 未初始化的全局变量(.bss段)
const int constGlobal = 200; // 常量(只读数据段)
void memorySegments() {
std::cout << "\n=== 内存分区演示 ===" << std::endl;
// 1. 栈内存(Stack)
int stackVar = 50; // 栈上分配
int array[100]; // 栈上数组(可能栈溢出)
// 2. 堆内存(Heap)
int* heapVar = new int(100); // 堆上分配单个int
int* heapArray = new int[1000]; // 堆上分配数组
// 3. 字符串常量池
const char* str1 = "Hello"; // 在常量池
const char* str2 = "Hello"; // 相同字符串共享
std::cout << "str1地址: " << (void*)str1 << std::endl;
std::cout << "str2地址: " << (void*)str2 << std::endl;
// 4. 验证栈和堆的地址差异
std::cout << "\n栈变量地址: " << &stackVar << std::endl;
std::cout << "堆变量地址: " << heapVar << std::endl;
std::cout << "全局变量地址: " << &globalVar << std::endl;
// 释放堆内存
delete heapVar;
delete[] heapArray;
}
// 演示栈帧
void functionA() {
int a = 10;
std::cout << "functionA - a地址: " << &a << std::endl;
}
void functionB() {
int b = 20;
std::cout << "functionB - b地址: " << &b << std::endl;
functionA();
}
int main() {
memorySegments();
std::cout << "\n=== 栈帧演示 ===" << std::endl;
int mainVar = 30;
std::cout << "main - mainVar地址: " << &mainVar << std::endl;
functionB();
return 0;
}
3.2 内存对齐与布局
cpp
#include <iostream>
#include <cstddef>
// 内存对齐示例
struct BadAlignment {
char c; // 1字节
int i; // 4字节(需要4字节对齐)
short s; // 2字节
// 总大小:1 + 3(填充) + 4 + 2 = 10字节(但会补齐到12)
};
struct GoodAlignment {
int i; // 4字节
short s; // 2字节
char c; // 1字节
// 总大小:4 + 2 + 1 + 1(填充) = 8字节
};
// 使用alignas指定对齐方式(C++11)
struct alignas(16) AlignedStruct {
double data[2]; // 16字节对齐
};
// 使用alignof获取对齐要求(C++11)
void alignmentDemo() {
std::cout << "\n=== 内存对齐演示 ===" << std::endl;
std::cout << "BadAlignment大小: " << sizeof(BadAlignment)
<< ", 对齐: " << alignof(BadAlignment) << std::endl;
std::cout << "GoodAlignment大小: " << sizeof(GoodAlignment)
<< ", 对齐: " << alignof(GoodAlignment) << std::endl;
std::cout << "AlignedStruct大小: " << sizeof(AlignedStruct)
<< ", 对齐: " << alignof(AlignedStruct) << std::endl;
// 查看成员偏移量
std::cout << "\nBadAlignment成员偏移:" << std::endl;
std::cout << "c: " << offsetof(BadAlignment, c) << std::endl;
std::cout << "i: " << offsetof(BadAlignment, i) << std::endl;
std::cout << "s: " << offsetof(BadAlignment, s) << std::endl;
}
3.3 RAII(资源获取即初始化)
cpp
#include <iostream>
#include <fstream>
#include <memory>
#include <mutex>
// 1. 文件资源的RAII包装
class FileHandle {
private:
std::FILE* file;
public:
explicit FileHandle(const char* filename, const char* mode = "r")
: file(std::fopen(filename, mode)) {
if (!file) {
throw std::runtime_error("无法打开文件");
}
std::cout << "文件打开: " << filename << std::endl;
}
~FileHandle() {
if (file) {
std::fclose(file);
std::cout << "文件关闭" << std::endl;
}
}
// 禁止拷贝
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
// 允许移动
FileHandle(FileHandle&& other) noexcept : file(other.file) {
other.file = nullptr;
}
FileHandle& operator=(FileHandle&& other) noexcept {
if (this != &other) {
if (file) std::fclose(file);
file = other.file;
other.file = nullptr;
}
return *this;
}
void write(const char* data) {
if (file) std::fputs(data, file);
}
};
// 2. 互斥锁的RAII包装
class ScopedLock {
private:
std::mutex& mtx;
public:
explicit ScopedLock(std::mutex& m) : mtx(m) {
mtx.lock();
std::cout << "锁已获取" << std::endl;
}
~ScopedLock() {
mtx.unlock();
std::cout << "锁已释放" << std::endl;
}
// 禁止拷贝和移动
ScopedLock(const ScopedLock&) = delete;
ScopedLock& operator=(const ScopedLock&) = delete;
ScopedLock(ScopedLock&&) = delete;
ScopedLock& operator=(ScopedLock&&) = delete;
};
// 3. 自定义内存管理的RAII
template<typename T>
class MemoryPool {
private:
T* pool;
size_t capacity;
public:
explicit MemoryPool(size_t size) : capacity(size) {
pool = static_cast<T*>(std::malloc(size * sizeof(T)));
if (!pool) {
throw std::bad_alloc();
}
std::cout << "内存池分配: " << size * sizeof(T) << " 字节" << std::endl;
}
~MemoryPool() {
if (pool) {
std::free(pool);
std::cout << "内存池释放" << std::endl;
}
}
T* allocate() {
return pool; // 简化实现
}
};
void raiiDemo() {
std::cout << "\n=== RAII演示 ===" << std::endl;
// 文件处理 - 异常安全
try {
FileHandle file("test.txt", "w");
file.write("Hello, RAII!\n");
// 即使这里抛出异常,文件也会正确关闭
} catch (const std::exception& e) {
std::cout << "异常: " << e.what() << std::endl;
}
// 锁管理 - 防止死锁
std::mutex mtx;
{
ScopedLock lock(mtx);
// 临界区代码
std::cout << "在临界区内操作" << std::endl;
} // 离开作用域自动释放锁
// 内存池
{
MemoryPool<int> pool(100);
int* data = pool.allocate();
// 使用data...
} // 自动释放内存池
}
int main() {
raiiDemo();
return 0;
}
3.4 常见内存问题与调试
cpp
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <new>
// 自定义new/delete操作符用于调试
void* operator new(size_t size) {
void* ptr = std::malloc(size);
std::cout << "分配内存: " << size << " 字节, 地址: " << ptr << std::endl;
if (!ptr) throw std::bad_alloc();
return ptr;
}
void operator delete(void* ptr) noexcept {
std::cout << "释放内存, 地址: " << ptr << std::endl;
std::free(ptr);
}
void memoryIssuesDemo() {
std::cout << "\n=== 常见内存问题演示 ===" << std::endl;
// 1. 内存泄漏
void leakMemory() {
int* leak = new int[100];
// 忘记 delete[] leak;
}
// 2. 悬空指针
void danglingPointer() {
int* ptr = new int(42);
delete ptr;
// ptr现在是指向已释放内存的悬空指针
// *ptr = 100; // 未定义行为!
}
// 3. 双重释放
void doubleFree() {
int* ptr = new int(42);
delete ptr;
// delete ptr; // 错误!再次释放同一内存
}
// 4. 缓冲区溢出
void bufferOverflow() {
char buffer[10];
// strcpy(buffer, "这个字符串太长了"); // 缓冲区溢出
std::strncpy(buffer, "安全拷贝", sizeof(buffer)-1);
buffer[sizeof(buffer)-1] = '\0'; // 确保以null结尾
}
// 5. 使用未初始化内存
void uninitializedMemory() {
int x; // 未初始化
// int y = x + 10; // 未定义行为
int x2 = 0; // 总是初始化变量
}
// 6. 内存碎片化演示
void memoryFragmentation() {
std::cout << "\n内存碎片化演示:" << std::endl;
// 分配和释放不同大小的内存块
void* blocks[10];
for (int i = 0; i < 10; i++) {
blocks[i] = new char[10 * (i + 1)]; // 不同大小
}
// 随机释放一些块
delete[] static_cast<char*>(blocks[2]);
delete[] static_cast<char*>(blocks[5]);
delete[] static_cast<char*>(blocks[8]);
// 现在尝试分配一个大块
try {
char* largeBlock = new char[100]; // 可能失败,即使总空闲内存足够
delete[] largeBlock;
} catch (const std::bad_alloc&) {
std::cout << "内存分配失败:碎片化问题" << std::endl;
}
// 清理
for (int i = 0; i < 10; i++) {
if (blocks[i]) {
delete[] static_cast<char*>(blocks[i]);
}
}
}
memoryFragmentation();
}
// 内存调试工具
class MemoryDebugger {
private:
static size_t totalAllocated;
static size_t totalFreed;
public:
static void* trackAlloc(size_t size, const char* file, int line) {
void* ptr = malloc(size);
totalAllocated += size;
std::cout << file << ":" << line
<< " - 分配 " << size << " 字节, 总计: "
<< totalAllocated << std::endl;
return ptr;
}
static void trackFree(void* ptr, size_t size, const char* file, int line) {
totalFreed += size;
std::cout << file << ":" << line
<< " - 释放 " << size << " 字节" << std::endl;
if (totalAllocated == totalFreed) {
std::cout << "所有内存已正确释放" << std::endl;
} else {
std::cout << "内存泄漏: " << (totalAllocated - totalFreed)
<< " 字节" << std::endl;
}
}
};
size_t MemoryDebugger::totalAllocated = 0;
size_t MemoryDebugger::totalFreed = 0;
// 重载new/delete进行跟踪
#define new new(__FILE__, __LINE__)
void* operator new(size_t size, const char* file, int line) {
return MemoryDebugger::trackAlloc(size, file, line);
}
void operator delete(void* ptr, size_t size) noexcept {
MemoryDebugger::trackFree(ptr, size, __FILE__, __LINE__);
free(ptr);
}
int main() {
memoryIssuesDemo();
std::cout << "\n=== 内存调试演示 ===" << std::endl;
int* debugPtr = new int(42);
delete debugPtr;
return 0;
}
四、在Android Framework中的应用
4.1 Android Native内存管理
cpp
// Android中的内存管理实践
#include <android/log.h>
#include <utils/RefBase.h> // Android的引用计数基类
#define LOG_TAG "NativeMemory"
#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
// 1. Android智能指针使用
class NativeObject : public android::RefBase {
public:
NativeObject() {
ALOGD("NativeObject创建");
}
virtual ~NativeObject() {
ALOGD("NativeObject销毁");
}
void doSomething() {
ALOGD("NativeObject操作");
}
};
// 2. 使用Android的sp/wp智能指针
void androidSmartPointerDemo() {
ALOGD("=== Android智能指针演示 ===");
// 强指针sp
android::sp<NativeObject> strongPtr = new NativeObject();
// 弱指针wp
android::wp<NativeObject> weakPtr = strongPtr;
// 提升弱指针
android::sp<NativeObject> promoted = weakPtr.promote();
if (promoted != nullptr) {
ALOGD("成功提升弱指针");
promoted->doSomething();
}
// 释放强指针
strongPtr.clear();
// 再次尝试提升
promoted = weakPtr.promote();
if (promoted == nullptr) {
ALOGD("弱指针已过期");
}
}
// 3. JNI中的内存管理
#include <jni.h>
extern "C" JNIEXPORT jlong JNICALL
Java_com_example_app_NativeLib_createNativeObject(JNIEnv* env, jobject thiz) {
// 创建Native对象,返回指针给Java层
NativeObject* obj = new NativeObject();
return reinterpret_cast<jlong>(obj);
}
extern "C" JNIEXPORT void JNICALL
Java_com_example_app_NativeLib_useNativeObject(JNIEnv* env, jobject thiz, jlong ptr) {
NativeObject* obj = reinterpret_cast<NativeObject*>(ptr);
if (obj) {
obj->doSomething();
}
}
extern "C" JNIEXPORT void JNICALL
Java_com_example_app_NativeLib_destroyNativeObject(JNIEnv* env, jobject thiz, jlong ptr) {
NativeObject* obj = reinterpret_cast<NativeObject*>(ptr);
delete obj;
}
// 4. Android中的内存对齐
#include <cutils/align.h>
void androidAlignment() {
void* ptr = malloc(100);
// Android提供的对齐函数
void* alignedPtr = (void*)ALIGN_UP((uintptr_t)ptr, 16);
ALOGD("原始指针: %p, 对齐后: %p", ptr, alignedPtr);
free(ptr);
}
// 5. Ashmem共享内存(Android特有)
#include <cutils/ashmem.h>
void sharedMemoryDemo() {
int fd = ashmem_create_region("shared_memory", 4096);
if (fd < 0) {
ALOGD("创建共享内存失败");
return;
}
// 设置保护模式
ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
// 映射到进程地址空间
void* addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) {
ALOGD("内存映射失败");
close(fd);
return;
}
// 使用共享内存
int* sharedData = static_cast<int*>(addr);
*sharedData = 42;
ALOGD("共享内存值: %d", *sharedData);
// 清理
munmap(addr, 4096);
close(fd);
}
4.2 最佳实践与性能优化
cpp
// C++内存管理最佳实践
class MemoryBestPractices {
public:
// 1. 使用现代C++特性
void modernCpp() {
// 使用auto避免类型错误
auto container = std::make_unique<std::vector<int>>();
// 使用范围for循环
for (const auto& item : *container) {
// 处理item
}
// 使用智能指针管理所有权
auto resource = std::make_shared<Resource>();
}
// 2. 避免不必要的拷贝
void avoidCopies(const std::string& input) { // 传递const引用
// 使用移动语义
std::string local = std::move(std::string(input)); // 示例
}
// 3. 使用reserve预分配内存
void reserveMemory() {
std::vector<int> numbers;
numbers.reserve(1000); // 预分配内存,避免多次重新分配
for (int i = 0; i < 1000; i++) {
numbers.push_back(i);
}
}
// 4. 使用对象池
class ObjectPool {
private:
struct PoolItem {
void* memory;
bool inUse;
};
std::vector<PoolItem> pool;
public:
void* allocate(size_t size) {
for (auto& item : pool) {
if (!item.inUse) {
item.inUse = true;
return item.memory;
}
}
// 创建新项
void* mem = malloc(size);
pool.push_back({mem, true});
return mem;
}
void deallocate(void* ptr) {
for (auto& item : pool) {
if (item.memory == ptr) {
item.inUse = false;
return;
}
}
}
};
// 5. 对齐内存访问
void alignedMemoryAccess() {
// 使用对齐的内存分配
alignas(64) int alignedArray[100]; // 64字节对齐,利于SIMD
// 对于动态分配
void* ptr = aligned_alloc(64, 1024); // C++17
if (ptr) {
// 使用对齐的内存
free(ptr);
}
}
// 6. 使用内存映射文件处理大文件
void memoryMappedFile(const char* filename) {
// 在实际Android开发中,使用系统调用
// int fd = open(filename, O_RDONLY);
// void* addr = mmap(NULL, fileSize, PROT_READ, MAP_PRIVATE, fd, 0);
// 处理文件内容...
// munmap(addr, fileSize);
// close(fd);
}
};
五、调试工具与性能分析
5.1 内存调试工具使用
cpp
// 内存调试技巧
#include <cassert>
void debuggingTechniques() {
std::cout << "\n=== 内存调试技巧 ===" << std::endl;
// 1. 使用assert进行运行时检查
int* ptr = new int(42);
assert(ptr != nullptr && "内存分配失败");
// 2. 边界检查
int array[10];
int index = 5;
assert(index >= 0 && index < 10 && "数组越界");
array[index] = 100;
// 3. 内存填充模式(调试时使用)
#ifdef DEBUG
constexpr unsigned char CLEAN_MEMORY = 0xCD; // 已分配但未初始化
constexpr unsigned char FREED_MEMORY = 0xDD; // 已释放
constexpr unsigned char GUARD_BYTE = 0xFD; // 边界保护
void* debugPtr = malloc(100);
memset(debugPtr, CLEAN_MEMORY, 100); // 填充特定模式
// 在边界添加保护字节
unsigned char* guardedPtr = new unsigned char[100 + 2];
guardedPtr[0] = GUARD_BYTE;
guardedPtr[100 + 1] = GUARD_BYTE;
// 检查保护字节是否被破坏
if (guardedPtr[0] != GUARD_BYTE || guardedPtr[100 + 1] != GUARD_BYTE) {
std::cout << "检测到内存破坏!" << std::endl;
}
#endif
delete ptr;
}
// 自定义内存分配器用于调试
template<typename T>
class DebugAllocator {
public:
using value_type = T;
DebugAllocator() = default;
template<typename U>
DebugAllocator(const DebugAllocator<U>&) {}
T* allocate(std::size_t n) {
std::size_t totalSize = n * sizeof(T) + sizeof(std::size_t);
void* ptr = malloc(totalSize);
if (!ptr) throw std::bad_alloc();
// 存储分配大小
*static_cast<std::size_t*>(ptr) = n;
// 返回分配的内存(跳过大小存储区)
T* result = reinterpret_cast<T*>(
static_cast<std::size_t*>(ptr) + 1);
std::cout << "分配 " << n << " 个 " << typeid(T).name()
<< " 对象,总大小: " << totalSize << std::endl;
return result;
}
void deallocate(T* ptr, std::size_t n) noexcept {
// 获取原始指针(包含大小信息)
void* originalPtr = static_cast<void*>(
static_cast<std::size_t*>(ptr) - 1);
// 读取分配时的大小
std::size_t allocatedSize = *static_cast<std::size_t*>(originalPtr);
if (allocatedSize != n) {
std::cout << "警告:分配大小(" << allocatedSize
<< ")与释放大小(" << n << ")不匹配" << std::endl;
}
std::cout << "释放 " << n << " 个 " << typeid(T).name()
<< " 对象" << std::endl;
free(originalPtr);
}
};
六、学习建议
6.1 学习路径规划
markdown
第一阶段(1-2个月):基础语法
├── 基本数据类型与运算符
├── 控制结构(循环、条件)
├── 函数与作用域
├── 数组与字符串
└── 结构体与类基础
第二阶段(2-3个月):面向对象与内存
├── 类与对象深入
├── 继承与多态
├── 内存管理基础
├── 指针与引用
└── 基本模板编程
第三阶段(3-4个月):现代C++与实战
├── 智能指针与RAII
├── 移动语义与右值引用
├── STL容器与算法
├── Lambda表达式
└── 并发编程基础
第四阶段(持续):深入Android Framework
├── Android Native开发
├── JNI编程
├── Android智能指针
└── Framework源码分析
6.2 实践项目建议
- 基础项目:实现一个简单的字符串类(带拷贝控制)
- 中级项目:实现一个智能指针模板类
- 高级项目:实现一个简单的对象池内存管理器
- Android项目:编写JNI代码,实现Java与C++的数据交换
6.3 重要习惯养成
- 内存安全第一:始终使用智能指针,除非有特殊需求
- RAII原则:资源获取即初始化,利用对象生命周期管理资源
- 避免裸指针:尽量减少使用原始指针
- 性能意识:了解内存对齐、缓存友好性等概念
- 调试技巧:学会使用Valgrind、AddressSanitizer等工具
七、常见面试题
Q1:new/delete和malloc/free的区别?
答案:
- 类型安全:new返回具体类型指针,malloc返回void*
- 构造/析构:new调用构造函数,delete调用析构函数
- 内存大小:new自动计算大小,malloc需要手动指定
- 异常处理:new分配失败抛异常,malloc返回nullptr
- 重载能力:new/delete可以重载,malloc/free不能
- 内存来源:new从自由存储区分配,malloc从堆分配
Q2:什么是内存泄漏?如何检测和避免?
答案 : 内存泄漏:已分配的内存无法被访问且无法被释放。
检测方法:
- 使用工具:Valgrind、AddressSanitizer、Visual Studio诊断工具
- 重载new/delete记录分配和释放
- 使用智能指针进行自动管理
避免方法:
- 使用RAII模式
- 优先使用智能指针
- 遵循谁分配谁释放的原则
- 使用容器类而不是原始数组
Q3:C++11的移动语义有什么作用?
答案:
- 避免不必要的拷贝:通过移动而非拷贝转移资源
- 提高性能:移动操作通常比拷贝快得多
- 实现完美转发:保持参数的值类别(左值/右值)
- 支持不可拷贝类型的转移:如unique_ptr
cpp
// 示例:移动构造 vs 拷贝构造
class Resource {
int* data;
public:
// 移动构造函数
Resource(Resource&& other) noexcept : data(other.data) {
other.data = nullptr; // 转移所有权
}
// 拷贝构造函数
Resource(const Resource& other) {
data = new int[100];
std::copy(other.data, other.data + 100, data); // 深拷贝
}
};
总结
C++内存管理是系统级开发的核心技能,特别是对于Android Framework开发。关键点:
- 理解内存分区:栈、堆、全局区、常量区
- 掌握智能指针:unique_ptr、shared_ptr、weak_ptr
- 实践RAII原则:利用对象生命周期管理资源
- 熟悉现代C++:移动语义、Lambda、auto等特性
- 学习Android特定实践:sp/wp智能指针、JNI内存管理
在学习过程中,要边学边练,通过实际项目加深理解。Framework开发需要扎实的C++基础,但更重要的是工程实践能力和调试技巧。