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

相关推荐
xiaoqider11 小时前
C++模板进阶
开发语言·c++
移幻漂流11 小时前
C/C++并发编程详解:如何写出优秀的并发程序
c语言·开发语言·c++
被星1砸昏头12 小时前
C++中的享元模式
开发语言·c++·算法
D_evil__12 小时前
【Effective Modern C++】第三章 转向现代C++:7. 在创建对象时注意区分()和{}
c++
Bruce_kaizy13 小时前
c++ dfs搜索算法——剪枝
c++·深度优先·剪枝
CSDN_RTKLIB13 小时前
【std::string】find函数
c++·stl
十五年专注C++开发13 小时前
浅谈CPU中的SIMD
c++·cpu·代码优化·simd
Yu_Lijing13 小时前
基于C++的《Head First设计模式》笔记——状态模式
c++·笔记·设计模式
顶点多余14 小时前
静态链接 vs 动态链接,静态库 vs 动态库
linux·c++·算法
AI视觉网奇14 小时前
ue5 开发 web socket server 实战2026
c++·学习·ue5