c++中的内存管理:栈,堆及RALL机制

以下知识和部分代码学习自Light-City/CPlusPlusThings: C++那些事 (github.com)

c++ 复制代码
class Obj{
public:
   Obj()=default;
   ~Obj()=default;
};
//栈:自动管理内存
void stack_example()
{
    Obj s; //栈上创建对象
    //离开作用域后自动销毁
}

c++ 复制代码
class Obj{
public:
   Obj()=default;
   ~Obj()=default;
};
void heap_exmaple()
{
    Obj* s=new Obj(); //堆上创建对象
    
    //同时如果这里抛出异常,后面的delete不会执行
    
    delete s;//需要手动删除
}

从以上例子看出栈和堆的内存分配方式完全不同,栈会自动分配和释放,不会发生内存泄漏。而堆要求我们 手动管理,无论是忘记加delete,还是抛出异常,都会造成内存泄漏。

RALL:资源获取即初始化

总的来说RALL即:

1,资源在构造函数中获得

2,资源在析构函数中释放

3,类的实例由堆栈控制

一下是代码演示:

c++ 复制代码
#include <iostream>
#include <mutex>
#include <fstream>
using namespace std;
// RAII 资源获取即初始化,例1

enum class shape_type {
    circle,
    triangle,
    rectangle,
};


class shape {
public:
    shape() { cout << "shape" << endl; }

    virtual void print() {
        cout << "I am shape" << endl;
    }

    virtual ~shape() {}
};

class circle : public shape {
public:
    circle() { cout << "circle" << endl; }

    void print() {
        cout << "I am circle" << endl;
    }
};

class triangle : public shape {
public:
    triangle() { cout << "triangle" << endl; }

    void print() {
        cout << "I am triangle" << endl;
    }
};

class rectangle : public shape {
public:
    rectangle() { cout << "rectangle" << endl; }

    void print() {
        cout << "I am rectangle" << endl;
    }
};

shape *create_shape(shape_type type) {
    switch (type) {
        case shape_type::circle:
            return new circle();
        case shape_type::triangle:
            return new triangle();
        case shape_type::rectangle:
            return new rectangle();
    }
}

class shape_wrapper {
public:
    explicit shape_wrapper(shape *ptr = nullptr) : ptr_(ptr) {}

    ~shape_wrapper() {
        delete ptr_;
    }

    shape *get() const {
        return ptr_;
    }

private:
    shape *ptr_;
};


void foo() {
    shape_wrapper ptr(create_shape(shape_type::circle));
    ptr.get()->print();
}

int main() {

    // 第一种方式
    shape *sp = create_shape(shape_type::circle);
    sp->print();
    delete sp;

    // 第二种方式 RAII
    foo();

    return 0;
}

对象切片问题

这个问题是我在刚接触c++时非常容易犯得错误,即把一个派生类对象直接赋值给一个基类对象。

c++ 复制代码
int main() {

    circle object;
    shape sp = object;
    sp.print();

    return 0;
}

此时结果如下:

c++ 复制代码
shape
circle
I am shape

简单来说派生类"多出来"的部分被切掉了,只剩下基类部分。因此我们永远不要通过值传递将派生类传递给基类,而要使用指针和引用。

智能指针

c++11后引入了智能指针,如unique_ptr,shared_ptr。使用智能指针不仅可以解决堆内存需要手动分配的问题和对象切片问题,还能使代码更加优雅简洁。所以请毫不犹豫使用智能指针。

相关推荐
xh didida7 分钟前
C++ -- string
开发语言·c++·stl·sring
m晴朗30 分钟前
测试覆盖率从35%到80%:我用AI批量生成C++单元测试的完整方案
c++·gpt·ai
无限进步_33 分钟前
【C++&string】大数相乘算法详解:从字符串加法到乘法实现
java·开发语言·c++·git·算法·github·visual studio
苏纪云1 小时前
蓝桥杯考前突击
c++·算法·蓝桥杯
‎ദ്ദിᵔ.˛.ᵔ₎1 小时前
模板template
开发语言·c++
charlie1145141911 小时前
通用GUI编程技术——图形渲染实战(二十九)——Direct2D架构与资源体系:GPU加速2D渲染入门
开发语言·c++·学习·架构·图形渲染·win32
小肝一下1 小时前
每日两道力扣,day8
c++·算法·leetcode·哈希算法·hot100
CheerWWW1 小时前
C++学习笔记——线程、计时器、多维数组、排序
c++·笔记·学习
无限进步_1 小时前
【C++】验证回文字符串:高效算法详解与优化
java·开发语言·c++·git·算法·github·visual studio
charlie1145141912 小时前
嵌入式现代C++工程实践——第10篇:HAL_GPIO_Init —— 把引脚配置告诉芯片的仪式
开发语言·c++·stm32·单片机·c