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

相关推荐
无限进步_2 小时前
【C语言】用队列实现栈:数据结构转换的巧妙设计
c语言·开发语言·数据结构·c++·链表·visual studio
千里马-horse4 小时前
TypedArrayOf
开发语言·javascript·c++·node.js·napi
YIN_尹4 小时前
【C++11】lambda表达式(匿名函数)
java·c++·windows
陳10304 小时前
C++:vector(2)
开发语言·c++
盖世灬英雄z4 小时前
数据结构与算法学习(一)
c++·学习·排序算法
CodeOfCC4 小时前
C++ 基于kmp解析nalu
c++·音视频·实时音视频·h.265·h.264
Sheep Shaun4 小时前
STL中的map和set:红黑树的优雅应用
开发语言·数据结构·c++·后端·c#
1001101_QIA5 小时前
【C++笔试题】递归判断数组是否是递增数组
开发语言·c++
qq_401700416 小时前
C/C++中的signed char和unsigned char详解
c语言·c++·算法