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

相关推荐
C++ 老炮儿的技术栈2 小时前
volatile使用场景
linux·服务器·c语言·开发语言·c++
hz_zhangrl2 小时前
CCF-GESP 等级考试 2026年3月认证C++一级真题解析
开发语言·c++·gesp·gesp2026年3月·gespc++一级
Liu628882 小时前
C++中的工厂模式高级应用
开发语言·c++·算法
波特率1152002 小时前
const关键字与函数的重载
开发语言·c++·函数重载
干啥啥不行,秃头第一名3 小时前
C++20概念(Concepts)入门指南
开发语言·c++·算法
2301_807367193 小时前
C++中的解释器模式变体
开发语言·c++·算法
2301_819414305 小时前
C++与区块链智能合约
开发语言·c++·算法
不想看见4045 小时前
Valid Parentheses栈和队列--力扣101算法题解笔记
开发语言·数据结构·c++
老约家的可汗6 小时前
C/C++内存管理探秘:从内存分布到new/delete的底层原理
c语言·c++
天赐学c语言6 小时前
Linux - 应用层自定义协议与序列/反序列化
linux·服务器·网络·c++