C++高级进阶--夯实进阶基础(1)

高级核心

指针的深度理解

函数指针

含义:函数指针是一个指针变量,他存的不是数值,而是这个函数的地址

  1. 程序运行时,函数会加载到内存,有地址空间
  2. 函数指针就直指向这个地址的指针
  3. 函数指针可以把函数当作参数传递,动态调用函数

函数指针的定义格式

1.普通的使用

复制代码
返回值类型 (*指针名)(参数列表);
int add(int a, int b) { return a+b; }
// 函数指针定义
int (*p)(int, int);
p = add;  // 让指针 p 指向 add 函数
int res = p(1,2); // 等价 add(1,2)

2.函数指针作为参数使用

复制代码
void print(int x) { cout << x << endl; }

void doSomething(int a, void (*cb)(int)) {
    cb(a); // 调用传入的函数
}

int main() {
    doSomething(100, print);
}

3.C++11的简化写法

复制代码
using Func = int(*)(int,int);
//等同于
typedef int(*Func)(int,int);

4.lambda表达式

  1. 可以随时定义、就地使用的匿名函数,不用单独写函数名
复制代码
   [捕获列表] (参数) -> 返回值 { 函数体 };

   捕获列表

   [=]:值捕获,外部变量只读
   [&]:引用捕获,外部变量可修改
   [x, &y]:x 值捕获,y 引用捕获
   [this]:在类里捕获当前对象

   auto add = [](int a, int b) { return a + b; };
   cout << add(1,2); // 输出3
  1. lambda表达式的本质是仿函数 类里面重写了()运算符重载 因此可以向函数指针一样使用。

5.std::function可调用对象包装器

一个可调用对象包装器,能装:函数、函数指针、lambda、成员函数。

复制代码
#include <functional>

std::function<int(int, int)> func;
func = [](int a,int b){return a+b;};
cout << func(1,2);

6.std::bind参数绑定器

用来绑定函数 + 参数,生成一个新的可调用对象。

复制代码
占位符:std::placeholders::_1 表示第一个参数

绑定普通函数
void add(int a,int b) { cout<<a+b; }
auto f = std::bind(add, 10, std::placeholders::_1);
f(20); // 输出 30

绑定成员函数:
std::bind(&类::函数, 对象指针/引用, 参数...);
指针数组

含义:一个数组,数组里的每个元素都是指针。

  • 本质是数组
  • 数组里存的不是普通值,是地址(指针)
复制代码
  int* arr[5];
  这就是: *一个大小为 5 的数组,每个元素都是 int 类型的指针。**

和数组指针区分:

指针数组:int *arr[10];数组,里面是指针

数组指针:int (*arr)[10];指针,指向一个数组

口诀: 括号优先是指针,无括号是数组。

二级指针

含义:二级指针就是:用来存放 一级指针地址 的指针。

  • 一级指针:int *p → 存放变量地址
  • 二级指针:int **pp → 存放一级指针的地址
void*

定义:void *是可以指向任意类型数据的通用指针

内存四区

含义:由系统自动管理,自动分配、自动释放

存放:局部变量、函数参数、函数调用

手动申请、手动释放

存放new/malloc 出来的动态数据

数据段

存放全局数据、静态数据****程序整个运行期间都存在

分为:

已初始化数据:全局变量、static 变量

未初始化数据(BSS):未赋值的全局变量

代码段

存放程序代码、二进制指令

只读,不能修改

函数名、代码地址都在这里

结构体、内存对齐、位域

结构体

定义:结构体是用户自定义的复合数据类型,把多个不同类型的变量打包在一起。

复制代码
struct Student {
    int id;
    char name[10];
    float score;
};
  • 可以存不同类型数据
  • 默认权限 public
  • 占用内存 = 所有成员总和 + 内存对齐填充
内存对齐

目的:为了让 CPU 读取更快,提高访问效率。

三大对齐规则:

  • 第一个成员从偏移 0 开始

  • 每个成员的起始地址 = 自身大小的整数倍

  • 结构体总大小 = 最大成员大小的整数倍

举一个例子:

复制代码
struct A {
    char a;   // 1字节
    int b;    // 4字节
    short c;  // 2字节
};

计算:
char a:1 字节 → 偏移 0
填充 3 字节(让 int 从 4 的倍数开始)
int b:4 字节 → 偏移 4~7
short c:2 字节 → 偏移 8~9
总大小:10 → 补齐到最大成员 int (4) 的倍数 → 12 字节
答案:sizeof (A) = 12
位域

定义:把一个变量按 "二进制位" 来分配空间,节省内存。

格式:

复制代码
struct Test {
    int a : 3;   // 占3位
    int b : 4;   // 占4位
    int c : 5;   // 占5位
};

特点 节省内存 单位是位(bit) 不能取地址 & 只能用于整型(char/short/int)

用途 网络协议包 硬件寄存器 存储空间极小的配置项

编译流程

预编译

处理以 # 开头的指令 展开 #include 头文件 处理条件编译 #if #ifdef #endif 删除注释

.c/.cpp ->.i

编译

把预处理后的代码 → 汇编代码 语法检查 词法分析 语义分析

.i -> .s

汇编

把汇编代码 → 二进制机器码 生成目标文件只翻译,不合并

.s -> .o

链接

把多个目标文件 + 库文件 → 可执行程序 合并代码段、数据段 解析函数地址 链接静态库 / 动态库 生成最终可执行文件

.o/.obj -> .exe

面向对象的深度理解

构造 / 析构函数、拷贝构造、移动构造(C++11)

1. 构造函数
  • 作用 :创建对象时初始化成员变量
  • 特点:与类同名,无返回值,可重载
  • 分类:默认构造、有参构造、拷贝构造、移动构造
2. 析构函数
  • 作用 :对象销毁时释放资源(如 new 的内存)
  • 格式~类名(){}
  • 特点:无参无返回值,一个类只有一个
  • 重点 :有动态分配内存时,必须写析构!
3. 拷贝构造函数(深拷贝 / 浅拷贝必考)
  • 作用 :用一个已有对象初始化新对象
  • 格式类名(const 类名& other)
  • 浅拷贝 :只拷贝地址,会导致重复释放内存
  • 深拷贝:重新开辟内存,拷贝内容,安全!
4. 移动构造函数(C++11)
  • 作用转移临时对象(右值)资源,避免拷贝,提高效率

  • 格式类名(类名&& other)

  • 特点:窃取资源,不拷贝,效率高

    #include
    class A {
    public:
    //构造函数
    A(int a1,int* c1,int&d1):a(a1),d(d1){
    c = new int(c1);
    std::cout << "A 构造函数调用" << std::endl;
    }
    //析构函数
    ~A(){
    if (c != nullptr) {
    delete c;
    std::cout << "A 析构函数调用" << std::endl;
    }
    }
    //拷贝构造
    A(const A& other):a(other.a),d(other.d) {
    c = new int(
    (other.c));
    std::cout << "A 拷贝构造函数调用" << std::endl;
    }
    //赋值运算符重载
    A& operator=(const A& other) {
    if (&other != this) {
    *c = other.c;
    }
    std::cout << "赋值运算符重载函数调用" << std::endl;
    }
    //移动构造函数
    A(A&& other):a(other.a), d(other.d) {
    delete c;
    c = other.c;
    other.c = nullptr;
    std::cout << "/移动构造函数调用" << std::endl;
    }
    private:
    const int a;
    static int b;
    int
    c = nullptr;
    int& d;
    };
    int A::b = 0;

RAII 机制(C++ 核心思想)

RAll机制:资源获取即初始化 在创建对象前进行构造,销毁对象时进行析构。

核心思想:

  • 利用栈对象自动销毁的特性,管理动态资源
  • 构造时获取资源
  • 析构时自动释放资源
  • 保证不泄漏资源、不重复释放、异常安全

经典应用

unique_ptr
核心特点
  • 独占所有权,同一时间只能有一个指针指向对象

  • 禁止拷贝,不能赋值给另一个 unique_ptr

  • 可以移动(move)

  • 效率极高,和裸指针一样快

  • 离开作用域自动 delete

复制代码
#include<iostream>
template<typename T>
class my_unique {
	T* _ptr;
	// 禁止拷贝(重点)
	my_unique(const my_unique&) = delete;
	my_unique& operator=(const my_unique&) = delete;
public:
	my_unique(T* p =nullptr):_ptr(p){}
	my_unique() { delete _ptr; }
	// 支持移动
	my_unique(my_unique&& other) {
		_ptr = other._ptr;
		other._ptr = nullptr;
	}
	T* operator->() { return _ptr; }
	T& operator*() { return *_ptr; }
};
shared_ptr
核心特点
  • 共享所有权,多个指针指向同一个对象

  • 内部有引用计数(reference count)

  • 拷贝一次,计数 +1

  • 销毁一次,计数 -1

  • 计数变为 0 才真正释放对象

复制代码
template<typename T>
class my_shared {
	T* _ptr;
	int* c;
public:
    // 构造
    my_shared(T* p = nullptr) : _ptr(p) {
        if (_ptr) {
            _count = new int(1);
        }
    }

    // 拷贝构造(计数+1)
    my_shared(const my_shared& other) {
        _ptr = other._ptr;
        _count = other._count;
        if (_count) (*_count)++;
    }

    // 析构(计数-1,为0释放)
    ~my_shared() {
        if (_count) {
            (*_count)--;
            if (*_count == 0) {
                delete _ptr;
                delete _count;
            }
        }
    }

    T* operator->() { return _ptr; }
    T& operator*() { return *_ptr; }
    int use_count() { return *_count; }
};
weak_ptr
核心特点
  • 指向 shared_ptr 管理的对象
  • 不增加引用计数
  • 不能直接使用 *->
  • 必须调用 lock() 转为 shared_ptr 才能用
  • 解决 shared_ptr 循环引用导致内存泄漏
复制代码
template <typename T>
class weak_ptr {
private:
    T* _ptr;
    int* _count;

public:
    weak_ptr() : _ptr(nullptr), _count(nullptr) {}

    // 从 shared_ptr 构造
    weak_ptr(shared_ptr<T>& other) {
        _ptr = other._ptr;
        _count = other._count;
        // 重点:不增加引用计数!
    }

    // 提升为 shared_ptr
    shared_ptr<T> lock() {
        return shared_ptr<T>(*this);
    }

    bool expired() {
        return (_count == nullptr || *_count == 0);
    }
};
相关推荐
梦想三三1 小时前
【PYthon词频统计与文本向量化】苏宁易购评论分析实战
开发语言·python
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题 第93题】【Mysql篇】第23题:从查找速度来看,聚集索引和非聚集索引哪个更快?
java·开发语言·数据库·mysql·面试
Cheng小攸2 小时前
入侵检测环境部署
开发语言·php
郝学胜-神的一滴2 小时前
中级OpenGL教程 008:精准控制高光光斑大小与强度
c++·unity·godot·three.js·图形学·opengl·unreal
我是唐青枫2 小时前
Java MyBatis-Flex 实战指南:从 BaseMapper 到 QueryWrapper 的轻量 ORM 用法
java·开发语言·mybatis
牢姐与蒯3 小时前
c++数据结构之c++11(一)
数据结构·c++
ShyanZh3 小时前
Markitdown 多格式文档智能解析实战指南
开发语言·c#
一只专注api接口开发的技术猿3 小时前
OpenClaw 对接淘宝商品 API,低成本实现全天候选品监控|附可运行 Python 实操代码
大数据·开发语言·数据库·python
xingpanvip3 小时前
星盘接口开发文档:马盘次限盘接口指南
android·开发语言·python·php·lua