当前位置: 首页 > news >正文

C++智能指针上

一、裸指针

        “裸指针”是最基础的,直接存储内存地址的指针类型。特点:①它本身没有自动的内存管理机制:如它不会自动释放内存,也不会检查是否指向有效的内存区域;②直接操作内存地址,不进行任何的边界检查:如空指针解引用。

int main()
{
    int x = 10;
    int*p = &x;           //裸指针p指向x
    cout << *p << endl;   //输出x的值,10
    return 0;
}

1、动态内存分配:new 与 malloc 详解

        在 C++ 中,动态内存分配是指在程序运行时(而非编译时)从堆(heap)上分配内存。主要有两种方式:new/delete:C++ 的运算符       malloc/free:C 标准库函数。

①new在堆分配的内存是无名的,返回一个指向该对象的指针。

    //分配单个对象
    int* p = new int;       //p指向一个动态分配的、未初始化的无名对象
    int* p2 = new int(42);  //分配并初始化为42
    int* p3 = new int();    //值初始化,*p3=0

    //分配数组
    int* arr = new int[10];//分配10个int的数组

    //释放内存
    delete p;
    delete[] arr;

②malloc返回void*,需要强制类型转换。

    //分配内存
    int* p = (int*)malloc(sizeof(int));          //分配一个int
    int* arr = (int*)malloc(10 * sizeof(int));   //分配10个int的数组

    //释放内存
    free(p);
    free(arr);

③两者区别:

a.基本内存分配与初始化:new支持初始化;malloc不初始化,分配后必须手动赋值,否则读取是未定义的行为。

b.类对象的内存管理:new自动调用构造函数,delete自动调用析构函数;malloc只是分配内存,需要配合placement new使用,且必须手动调用析构函数。

c.数组处理:new[]和delete[]配合使用;malloc需要手动计算数组大小、初始化每个元素。

d.内存分配失败处理:new在失败时抛出异常(std::bad_alloc);malloc在失败时返回NULL/nullptr。

e.与realloc的配合:

//new没有直接对应的realloc功能,需要手动实现:
    int* arrNew = new int[5];
    int* newArrNew = new int[10];
    std::copy(arrNew, arrNew + 5, newArrNew); //将 arrNew 的前5个元素复制到 newArrNew
    delete[] arrNew;
    arrNew = newArrNew;

//malloc可以配合realloc使用
    int* arr = (int*)malloc(5 * sizeof(int));
    // 扩展内存到10个int
    int* newArr = (int*)realloc(arr, 10 * sizeof(int));
    if (newArr)
    {
        arr = newArr;
        arr[8] = 42;  //使用新分配的空间
    }
    free(arr);

2、malloc两种内存分配方式

        ①brk()方式:分配小块内存(通常是小于128KB),通过brk()系统调用会将堆顶指针向更高的内存地址移动,获取内存空间。被free释放时,并不会将内存归还给操作系统,而是将其缓冲在内存池中,供后续分配请求复用。
优点:直接操作堆,内存分配速度较快。缺点:频繁使用,堆内将产生越来越多不可用的碎片,导致“内存泄漏”。
        ②mmap()方式:当用户请求的内存较大时(通常大于128KB),mmap()在进程的虚拟地址空间中(堆和栈的中间,称为文件映射区域的地方)找一块空闲的虚拟内存。free释放时,会把内存归还给操作系统,内存得到真正释放。
缺点:向操作系统申请内存,是通过系统调用的,执行系统调用是要进入内核态的,然后回到用户态,运行态的切换会耗费不少时间。分配的内存释放都会归还给操作系统。所以每次分配的虚拟地址都是缺页状态,在第一次访问该虚拟地址的时候,就会触发缺页中断。

二、智能指针

        “智能指针”是原始指针的封装,解决了裸指针带来的内存管理问题,可以自动管理内存的生命周期。

1、unique_ptr  “独占所有权”

①三种创建方式

#include <iostream>
using namespace std;
#include <memory>

class MyClass {
public:
    MyClass() { cout << "MyClass created!" << endl; }
    MyClass(int x, double y) {}    // 带参数的构造函数
    ~MyClass() { cout << "MyClass destroyed!" << endl; }
};

int main()
{
    //创建unique_ptr的三种方式:
    //1、使用make_unique  "推荐!!!"
    unique_ptr<MyClass> ptr = make_unique<MyClass>();//函数模板必须使用函数调用运算符 () 来调用。
    auto ptr1 = make_unique<MyClass>(42, 3.14); // 正确:传递参数

    //2、使用new运算符
    unique_ptr<MyClass> ptr2(new MyClass());
    //3、使用unique_ptr的构造函数
    MyClass* rawPtr = new MyClass();
    unique_ptr<MyClass> ptr3(rawPtr);

    return 0;
}

②成员函数get()获取原始指针(裸指针)

    MyClass* rawPtr = ptr.get();  //像普通指针一样使用它

注意:get()不改变所有权,unique_ptr仍然拥有资源的所有权,并在销毁时自动释放资源,手动对rawPtr调用delete会导致双重释放,尽量避免滥用get()。

③调用成员函数和解引用

④不可以copy只可以move

不允许复制是为了保证资源管理的唯一性。如果允许就会有多个指针共享相同的资源,导致双重释放等问题。

⑤reset()清空智能指针

reset方法将智能指针指向的对象释放,并将智能指针设置为nullptr。unique_ptr是独占拥有权,因此它会立即释放资源。

⑥作函数参数,值/引用/常量引用传递/右值引用

按值传递:传递所有权。

按引用传递:

常量引用传递时,函数无法修改指针的状态。

右值引用:值传递会触发一次移动构造,右值引用直接绑定到传入的右值,没有额外移动

                  传递所有权。

⑦以值返回:优化为移动,转移所有权。

http://www.xdnf.cn/news/126919.html

相关文章:

  • 如何在Spring Boot中禁用Actuator端点安全性
  • containerd 配置代理
  • 生成随机验证码-解析与优化
  • 扩张尺度张量填充方式
  • HTML字符实体和转义字符串
  • 【Linux】基本指令(下)
  • Docker部署DeepSeek常见问题及解决方案
  • 详细讲解 QMutex 线程锁和 QMutexLocker 自动锁的区别
  • 提升内容创作效率:AI原创文章批量生成工具优势
  • 【DNS】BIND 9的配置
  • Android之AI自动化测试--Midscene
  • CentOS 7上Memcached的安装、配置及高可用架构搭建
  • 内存管理:内存堆管理
  • 编译原理(5):链接
  • Kafka命令行的使用/Spark-Streaming核心编程(二)
  • 17.磁珠在EMC设计中的运用
  • Happens-Before 原则
  • 理解js函数(Ⅱ)
  • CompletableFuture到底怎么用?
  • Code Splitting 分包策略
  • MobTech袤博ShareSDK集成错误 ld: symbol(s) not found for architecture arm64
  • 《一文读懂Transformers库:开启自然语言处理新世界的大门》
  • 【重走C++学习之路】18、map和set
  • 基于RFID的智能家居系统设计与实现
  • Spring—依赖注入注解
  • 从认证到透传:用 Nginx 为 EasySearch 构建一体化认证网关
  • 【Java 8新特性】Stream API 和 Lambda 表达式
  • MySQL数据库基本操作-DQL-基本查询
  • 多线程事务?拿捏!
  • 豆包桌面版 1.47.4 可做浏览器,免安装绿色版