动态内存管理类

内存管理类需要包括以下几个基本操作的正确性

  1. 添加元素:判断管理的空间大小是否能够添加新元素,如不够,则使用allocator分配内存,并将旧数据移动到新内存,然后释放旧内存,并更新内存首指针、第一个可用内存指针、尾指针位置。
  2. 对象拷贝:使用allocator的allocate分配内存,相关的uninitialized_copy拷贝元素到新的位置,并更新内存首指针、第一个可用内存指针、尾指针位置。
  3. 内存释放:使用allocator的destroy销毁内存,并使用deallocate执行内存回收操作

注意:静态对象必须首先在类外进行初始化操作。

//uninitialized_copy被编译器认为是不安全的,这语句是让编译器停止警告,放到第一行
#pragma warning(disable : 4996)
#include<iostream>
#include<string>
#include<memory>
using namespace std;
class StrVec
{
public:
    StrVec() :
        elements(nullptr), first_free(nullptr), cap(nullptr)
    {
    }
    //拷贝构造函数
    StrVec(const StrVec& s)
    {
        auto newdata = alloc_n_copy(s.begin(), s.end());
        elements = newdata.first;
        first_free = cap = newdata.second;
    }
    //拷贝赋值运算
    StrVec &operator=(const StrVec& rhs)
    {
        auto data = alloc_n_copy(rhs.begin(), rhs.end());
        free();
        elements = data.first;
        first_free = cap = data.second;
        return *this;
    }
    //析构函数
    ~StrVec() { free(); }
    //添加对象函数
    void push_back(const string& str)
    {
        chk_n_alloc();
        //在first_free位置构造元素
        alloc.construct(first_free++, str);
    }
    //输出内容
    void print(ostream& os)
    {
        for (auto pos = begin(); pos != end(); pos++)
            os << *pos << endl;
    }
    size_t size() const { return first_free - elements; }
    size_t capacity() const { return cap - elements; }
    string* begin() const { return elements; }
    string* end() const { return first_free; }

private:
    static allocator<string> alloc;
    void chk_n_alloc()
    {
        if (size() == capacity())
            reallocate();
    }
    //工具函数,被拷贝构造函数、赋值运算符和析构函数使用
    std::pair<string*, string*>alloc_n_copy(const string*b, const string*e)
    {
        auto data = alloc.allocate(e - b);
        return{ data,uninitialized_copy(b,e,data) };
    }
    //销毁元素,释放内存
    void free()
    {
        //不能传递给一个空指针,为0什么也不做
        if (elements)
        {
            for (auto p = first_free; p != elements;)
                alloc.destroy(--p);
            alloc.deallocate(elements, cap - elements);
        }
    }
    //获得更多内存,拷贝已有元素
    void reallocate()
    {
        //分配两倍内存
        auto newcapacity = size() ? 2 * size() : 1;
        //分配新内存
        auto newdata = alloc.allocate(newcapacity);
        //数据从旧内存移动到新内存
        auto dest = newdata;//指向新内存中下一个可用位置
        auto elem = elements;//旧内存中下一个位置
        for (size_t i = 0; i != size(); i++)
            //移动的时候,通过move函数转换为右值引用,使用了移动构造函数构造对象
            alloc.construct(dest++, std::move(*elem++));
        free();//移动完成,释放旧内存
        //更新数据结构,换到新元素
        elements = newdata;
        first_free = dest;
        cap = elements + newcapacity;
    }
    //指向数组首元素指针
    string *elements;
    //指向数组第一个空闲元素的指针
    string *first_free;
    //指向数组尾后位置
    string *cap;
};
allocator<string> StrVec::alloc;

使用时

int main()
{
    {
        StrVec strVec;
        strVec.push_back("asdfasdf");
        //strVec.push_back("123456");
        //strVec.push_back("[email protected]#$%^&");
        //strVec.push_back("[email protected]#$%^&");
        auto strVec1 = strVec;
        strVec1.push_back("[email protected]#$%^&");
        strVec.print(cout);
        strVec1.print(cout);
    }
    _CrtDumpMemoryLeaks();
}
时间: 2024-08-06 02:19:11

动态内存管理类的相关文章

浅谈C++容器动态内存管理的优化

在信息学竞赛中,C++的容器的用途非常广泛,但经常因常数过大而超时.怎样才能提高它们的效率呢? 我们知道,容器是存储同一类对象的对象,既然"对象"我们无法改变,那么我们只能从"存储"入手,不难想到,不同容器在实现上的根本区别是它们对应着不同的内存组织方式,内存管理无疑是这种实现的核心,所以优化内存管理是加快容器效率的最好途径之一. 一.内存分配器简介 怎样才能优化内存管理呢?很简单,C++为我们提供了这样的接口,我们可以通过自定义容器模板中的最后一个allocato

c++中的动态内存管理

c++中的动态内存管理问题 c++中使用new和delete实现动态内存管理.new和delete实现动态管理对象,new[]和delete[]实现动态管理对象数组.c++中的new和delete运算符均使用我们c中学过的malloc和delete函数实现动态内存的开辟. 首先,先简单介绍下c中的几个动态内存函数malloc,realloc,calloc,free; void *malloc(size_t size); //动态内存开辟函数 void free(void *pointer);  

c++动态内存管理

一.内存的常见分配方式 1. 从静态区分配,一般是全局变量和static类型变量 2.从栈区分配内存,一般是局部的变量,会随着所在函数的结束而自动释放 3.从堆中分配,一般是使用手动分配,使用malloc()函数和new来申请任意大小空间,不过要手动释放空间,相应的使用free()函数和delete释放, 如果不释放该空间,而且指向该空间的指针指向了别的空间.则该空间就无法释放,造成内存泄露,造成了内存浪费 二.内存的使用规则 1.在使用malloc()或new申请空间时,要检查有没有分配空间成

C++动态内存管理之shared_ptr、unique_ptr

C++中的动态内存管理是通过new和delete两个操作符来完成的.new操作符,为对象分配内存并调用对象所属类的构造函数,返回一个指向该对象的指针.delete调用时,销毁对象,并释放对象所在的内存.但在程序中使用new和delete容易导致很多问题,这里列出三个比较容易犯的错误. 我们new了一个对象,但没有delete它.这会引起memory leak内存泄露,可能会导致程序崩溃. 用指针访问一个已经被free的对象.这就是我们常说的dangling pointer. delelte同一个

C++函数中,两个自动释放内存的动态内存申请类

最近做一个事情,实现一个流程交互,其中主交互流程函数中,涉及较多的内存申请, 而健康的函数,都是在函数退出前将手动申请不再需要的内存释放掉, 使用很多方法,都避免不了较多的出错分支时,一堆的if free/delete,代码长而且不好管理 因此,利用C++对象离开作用域会自动调用析构函数的特点,在这儿实现了两个自动释放内存的动态内存申请类 第一个类,只管理内存,不并管理对象 #include <vector> class XAutoFreeMem { protected: std::vecto

动态内存管理

(1).c中动态内存管理方式 malloc.calloc.realloc在堆上开辟空间.free将申请的空间释放掉 void *malloc( size_t size );      void *calloc( size_t num, size_t size );      void *realloc( void *memblock, size_t size ); (2).C++中动态内存管理 通过new和delete运算符进行动态内存管理 (3).malloc/free和new/delete的

iOS开发之c语言基础Lesson-10 动态内存管理 上课笔记 与 试题练习

//函数声明 int max(int a, int b); char * getString(); int main(int argc, const char * argv[]) { //////////////////Lesson 10 动态内存管理 课堂笔记 和 练习 ///////复习上周所学 /////////常量和变量的区别: //常量中的内容不能被修改,只能访问: //变量中存储的数据时可以随时修改的. // //const 关键字的作用: 修饰变量不可改变.当做常量使用 //  c

C语言动态内存管理

1-概述 动态存储管理的基本问题是:系统如何按请求分配内存,如何回收内存再利用.提出请求的用户可能是系统的一个作业,也可能是程序中的一个变量. 空闲块 未曾分配的地址连续的内存区称为"空闲块". 占用块 已分配给用户使用的地址连续的内存区称为"占用块". 系统刚刚启动时,整个内存可看做一个大的"空闲块",随着用户请求的进入,系统依次分配相应的内存. 在系统运行过程中,内存被分为两大部分:低地址区(若干占用块)和高地址区(空闲块). 经过一段时间后

动态内存分配类实现

今天学习了C++语言的内存动态分配,并借助所学的知识实现了一个动态内存分配类. 问题的背景为:在已经实现了一个点类的基础上,实现一个动态内存分配类,这个类 的功能为:实现根据输入的数目size,动态的生成size个点类对象:并在提供一个借口 可以对pos位置的对象进行操作:在对象生存期结束时,可以自动释放分配的内存空间. 根据描述的问题描述的需求,规划了如下的类图: 写出了一个包含三个方法的对点动态分配内存的类: 1: #ifndef _ARRAYOFPOINTS_H 2: #define _A