C++中的new和delete

59 篇文章 0 订阅
52 篇文章 2 订阅

目录

摘要

常规用法

`new` 运算符

分配单个对象

分配数组

`delete` 运算符

释放单个对象

释放数组

高级用法

自定义 `new` 和 `delete` 运算符

自定义全局 `new` 和 `delete` 运算符

自定义类级别的 `new` 和 `delete` 运算符

定位 `new` 运算符

`new` 和 `delete` 与C++内核的关系

内存分配过程

关键点

注意事项

引用


摘要

在C++中,`new` 和 `delete` 运算符用于动态内存分配和释放,对它们的使用将会直接影响到程序的内存管理和性能优化。

常规用法

`new` 运算符

`new` 运算符在堆上分配内存,并调用对象的构造函数。它返回一个指向已分配内存的指针。

分配单个对象
#include <iostream>

int main() {
    int* p = new int;  // 分配一个整数
    *p = 5;           // 给分配的整数赋值
    std::cout << "Value: " << *p << std::endl;  // 输出整数值

    delete p;  // 释放内存
    return 0;
}
分配数组
#include <iostream>

int main() {
    int* arr = new int[10];  // 分配一个整数数组

    for (int i = 0; i < 10; ++i) {
        arr[i] = i;  // 给数组元素赋值
    }

    for (int i = 0; i < 10; ++i) {
        std::cout << arr[i] << " ";  // 输出数组元素
    }
    std::cout << std::endl;

    delete[] arr;  // 释放数组内存
    return 0;
}

`delete` 运算符

`delete` 运算符用于释放由 `new` 分配的内存,并调用对象的析构函数。

释放单个对象
#include <iostream>

int main() {
    int* p = new int(10);  // 分配并初始化一个整数
    std::cout << "Value: " << *p << std::endl;  // 输出整数值

    delete p;  // 释放内存
    return 0;
}
释放数组
#include <iostream>

int main() {
    int* arr = new int[10];  // 分配一个整数数组

    for (int i = 0; i < 10; ++i) {
        arr[i] = i;
    }

    delete[] arr;  // 释放数组内存
    return 0;
}

高级用法

自定义 `new` 和 `delete` 运算符

在C++中,可以自定义 `new` 和 `delete` 运算符,以实现特定的内存管理需求。

自定义全局 `new` 和 `delete` 运算符
#include <iostream>
#include <cstdlib>  // 使用 malloc 和 free

// 重载全局 new 运算符
void* operator new(std::size_t size) {
    std::cout << "Custom new for size: " << size << std::endl;
    void* p = std::malloc(size);
    if (!p) throw std::bad_alloc();
    return p;
}

// 重载全局 delete 运算符
void operator delete(void* p) noexcept {
    std::cout << "Custom delete" << std::endl;
    std::free(p);
}

int main() {
    int* p = new int(10);  // 将使用自定义的 new 运算符
    std::cout << "Value: " << *p << std::endl;

    delete p;  // 将使用自定义的 delete 运算符
    return 0;
}
自定义类级别的 `new` 和 `delete` 运算符
#include <iostream>
#include <cstdlib>  // 使用 malloc 和 free

class MyClass {
public:
    int value;

    MyClass(int v) : value(v) {}

    // 重载类级别的 new 运算符
    void* operator new(std::size_t size) {
        std::cout << "Custom class-level new for size: " << size << std::endl;
        void* p = std::malloc(size);
        if (!p) throw std::bad_alloc();
        return p;
    }

    // 重载类级别的 delete 运算符
    void operator delete(void* p) noexcept {
        std::cout << "Custom class-level delete" << std::endl;
        std::free(p);
    }
};

int main() {
    MyClass* obj = new MyClass(42);  // 使用自定义的类级别 new 运算符
    std::cout << "Value: " << obj->value << std::endl;

    delete obj;  // 使用自定义的类级别 delete 运算符
    return 0;
}

定位 `new` 运算符

定位 `new` 运算符允许在指定的内存地址上构造对象。这对于需要在预分配的内存块上构造对象的情况特别有用。

定位 `new`

#include <iostream>
#include <new>  // 使用定位 new

struct MyStruct {
    int x, y;
    MyStruct(int a, int b) : x(a), y(b) {
        std::cout << "MyStruct constructed" << std::endl;
    }
    ~MyStruct() {
        std::cout << "MyStruct destructed" << std::endl;
    }
};

int main() {
    char buffer[sizeof(MyStruct)];  // 预分配内存

    // 在预分配的内存上构造对象
    MyStruct* p = new (buffer) MyStruct(1, 2);
    std::cout << "p->x: " << p->x << ", p->y: " << p->y << std::endl;

    // 手动调用析构函数
    p->~MyStruct();

    return 0;
}

`new` 和 `delete` 与C++内核的关系

`new` 和 `delete` 运算符与C++内核(runtime library)有着紧密的联系。C++内核库负责管理内存的分配和释放。具体来说,标准库提供了 `malloc` 和 `free` 函数来实现低级别的内存管理,`new` 和 `delete` 运算符在其基础上进一步封装,实现了对象的构造和析构。

内存分配过程

1. new运算符:
    - 调用操作系统的内存分配函数(通常是 `malloc`)。
    - 分配成功后,调用对象的构造函数。
    - 返回指向新分配和初始化的对象的指针。

2. delete运算符:
    - 调用对象的析构函数。
    - 调用操作系统的内存释放函数(通常是 `free`)。

关键点

1. 异常安全:如果在构造函数中抛出异常,`new` 运算符会自动释放已分配的内存,以防止内存泄漏。
2. 全局重载:通过全局重载 `new` 和 `delete` 运算符,可以自定义内存分配策略,例如内存池、垃圾回收等。
3. 局部重载:类级别的 `new` 和 `delete` 运算符允许为特定类自定义内存管理。

异常安全

#include <iostream>
#include <new>  // 使用 std::bad_alloc

class MyClass {
public:
    MyClass() {
        std::cout << "Constructor" << std::endl;
        throw std::runtime_error("Exception in constructor");
    }
    ~MyClass() {
        std::cout << "Destructor" << std::endl;
    }
};

int main() {
    try {
        MyClass* obj = new MyClass();  // 构造函数中抛出异常
        delete obj;
    } catch (const std::exception& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }

    return 0;
}

注意事项

1. 内存泄漏:每个 `new` 必须对应一个 `delete`,否则会导致内存泄漏。
2. 数组分配和释放:分配数组时使用 `new[]`,释放数组时使用 `delete[]`,不要混用。
3. 智能指针:C++11 引入了智能指针(如 `std::unique_ptr` 和 `std::shared_ptr`),可以自动管理内存,减少手动调用 `new` 和 `delete` 的需要。

使用智能指针

#include <iostream>
#include <memory>  // 使用智能指针

int main() {
    std::unique_ptr<int> p = std::make_unique<int>(10);  // 自动管理内存
    std::cout << "Value: " << *p << std::endl;

    // 内存会在智能指针析构时自动释放
    return 0;
}

引用

new expression - cppreference.com

delete expression - cppreference.com

  • 25
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉夢志昂丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值