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。使用智能指针不仅可以解决堆内存需要手动分配的问题和对象切片问题,还能使代码更加优雅简洁。所以请毫不犹豫使用智能指针。

相关推荐
j7~几秒前
【C++】STL--string类--拆析解剖string类的实现以及string类的底层详解(2)
开发语言·c++·浅拷贝·深拷贝·string类的实现·string拷贝构造·string赋值重载
DogDaoDao27 分钟前
C++核心技术深度剖析:从底层原理到工程实践
开发语言·c++·面试·程序员·指针·虚函数
磊 子31 分钟前
C++移动语义和智能指针
java·开发语言·c++
不负岁月无痕34 分钟前
C++继承与多态知识点及其高频面试问题
开发语言·c++·面试
Tairitsu_H1 小时前
[LC优选算法#4] 滑动窗口 | 串联所有单词的⼦串 | 最⼩覆盖⼦串
c++·算法·滑动窗口
kyle~2 小时前
机器人日志系统
c++·单片机·嵌入式硬件·机器人·ros2
June`2 小时前
CUDA执行模型深入刨析
c++·人工智能·cuda
鱼子星_2 小时前
C++从零开始系列篇(一):C++入门——命名空间,输入输出与缺省参数
开发语言·c++
郝学胜-神的一滴2 小时前
CMake 015:日志级别全解析
linux·开发语言·c++·qt·程序人生·软件构建·cmake
FirstFrost --sy2 小时前
基于高并发服务器的web小游戏测试
服务器·前端·javascript·c++·python·集成测试