C++反汇编,指针和内存分配细节,面试题05

20. 指针 vs 引用

  • 指针是实体,占用内存空间,逻辑上独立;引用是别名,与变量共享内存空间,逻辑上不独立。
  • 指针定义时可以不初始化;引用定义时必须初始化。
  • 指针的值可以变,即可以指向别的内存地址;引用不变的。
  • 指针可以为nullptr;引用不能为空。
  • sizeof(指针)计算指针大小,由于指针保存的是内存地址,所以无论什么类型的指针,在32位程序里占4B,在64位程序里占8B;而sizeof(引用)计算引用对象的大小。
  • 指针自增用于地址偏移,运算结果取决于指针类型,因为当指针保存的是数组首地址时,为了能够利用指针自增后访问到数组下一成员,所以加的是类型长度,而非1,如下图;引用自增是引用对象自增。
    在这里插入图片描述
  • 指针取出数据内容时需要解引用;引用不需要。
  • 有二级指针;没有二级引用。
  • 【注意】 如果返回动态分配的内存,必须使用指针,使用引用会内存泄漏,如下图。
    在这里插入图片描述
    分析1:使用CRT库检测内存泄漏,4B,因为不能删除引用指向的内存地址,即使用 delete& ref 会触发中断
    在这里插入图片描述
    分析2:相比之下,使用指针返回动态分配的内存,可以在不需要时使用 delete释放内存,从而避免内存泄漏。

21. new vs malloc

  • new是C++运算符;malloc是C的库函数。
  • new返回指定类型指针;malloc返回void*指针,需要强制类型转换。
  • new自动计算需分配的空间;malloc需要指定分配空间的大小。
  • new可以被重载;malloc不能,代码如下。
#include<iostream>
using namespace std;

// 重载 new 操作符
void* operator new(size_t size) 
{
    cout << "Custom new: Allocating " << size << " bytes" << endl;

    void* ptr = std::malloc(size);
    if (!ptr) {
        throw std::bad_alloc(); // 内存分配失败时抛出异常
    }
    return ptr;
}

// 重载 delete 操作符
void operator delete(void* ptr) noexcept {
    cout << "Custom delete: Freeing memory" << endl;
    free(ptr);
}

int main() 
{
    int* arr = new int(4); 
    delete arr;
    return 0;
}

程序运行结果,如下图。
在这里插入图片描述

  • 代码如下,进行以下分析。
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include<iostream>
using namespace std;

class MyClass {
private:
    int* value;
public:
    MyClass(int v) : value(new int(v)) {
        printf("%s\n", "Constructor class");
    }

    ~MyClass()
    {
        delete value;
        printf("%s\n", "Delete class");
    }
};

int main() 
{
     MyClass* obj1 = new MyClass(42);

     MyClass* obj2 = (MyClass*)malloc(sizeof(MyClass));
     new(obj2) MyClass(44);

     delete obj1;
     free(obj2);

     _CrtDumpMemoryLeaks();
     return 0;
}
  • new会调用构造函数;malloc不会,即malloc只是分配内存空间,需要在其他地方初始化,如下图。
    在这里插入图片描述
    分析1:MyClass类大小,看它的数据成员大小,即4B。使用new时,先申请4B内存空间,然后调用构造函数进行初始化。
    请添加图片描述
    分析2:使用malloc时,只申请4B内存空间。然后使用new(obj2) MyClass(44);显示调用构造函数,进行初始化。
    在这里插入图片描述
    分析3:new的内部实现,会调用malloc分配内存空间。

  • 【注意】 new使用delete释放内存空间,在释放前会调用析构函数;malloc使用free释放内存空间,由于不会调用析构函数,会造成内存泄漏,如下图。
    请添加图片描述
    在这里插入图片描述

分析1:使用delete时,先调用析构函数释放对象内存空间,再释放指针内存空间。
请添加图片描述
分析2:使用free时,只释放指针内存空间,由于对象内存空间无法释放,造成内存泄漏。

相关推荐

  1. C语言指针内存管理

    2024-05-10 07:48:04       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-10 07:48:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-10 07:48:04       100 阅读
  3. 在Django里面运行非项目文件

    2024-05-10 07:48:04       82 阅读
  4. Python语言-面向对象

    2024-05-10 07:48:04       91 阅读

热门阅读

  1. Vue 传送门

    2024-05-10 07:48:04       27 阅读
  2. Linux习题和答案

    2024-05-10 07:48:04       38 阅读
  3. 十二届蓝桥杯Python组3月中/高级试题 第四题

    2024-05-10 07:48:04       31 阅读
  4. 负载均衡总结

    2024-05-10 07:48:04       38 阅读
  5. Ubuntu服务器命令行关机&重启&查询记录

    2024-05-10 07:48:04       37 阅读
  6. Nacos配置实时更新:微服务架构下的关键实践

    2024-05-10 07:48:04       32 阅读
  7. elasticsearch搭建教程

    2024-05-10 07:48:04       32 阅读
  8. Android ScrollView 在按键向下滚动后会回弹问题

    2024-05-10 07:48:04       32 阅读
  9. 六.音视频编辑-创建视频过渡-应用

    2024-05-10 07:48:04       22 阅读