什么是C ++动态内存分配?(What is Dynamic Memory Allocation i

2019-07-18 22:08发布

我学习用C动态内存分配++和关键字newnew[]被提及。 据说,以使用户在运行时,以指定的内存分配的大小,与简单地声明变量或阵列,以在源代码中的固定大小。

我不理解这个概念。 它是如何工作的? 我只需要在观念澄清和示例将是有益的!

Answer 1:

所以,如果你想在10个整数数组,你会写:

int arr[10]; 

但是,如果你想要做这样的事情是什么;

cout << "How many?";
cin >> num;

int arr[num];

那么,C ++语言不允许。 相反,你必须做的:

int *arr = new int[num]; 

以创建数组。 而后来,您必须在[1]使用:

delete [] arr; 

释放内存。

那么,如何工作的呢? 当你调用新的C ++运行时库会找出多少空间[你没有写,构成了C ++的基本代码] num整数占用,并找到在内存中的一些空间。 我不打算进入细节“你怎么找到一些记忆”。 现在,只要相信我,有一个可用于一些整数存储在一些可用内存的某个地方。

当你再打delete ,同样的内存归还给它原来的内存“池”或“堆”。

当然,如果你有,比如说,256 MB的内存的计算机,并尝试寻求空间来存储2.5亿整数,记住,一个整数占用多于一个字节的轴承,它不会去上班了 - 有没有“神奇”在这里 - 在内存仍然局限于有多少是在机器可用....你必须要确定程序的权利,当它的运行,有多少内存需要,而不必编写程序时决定。

编辑:这通常是最好的“隐藏”使用为这个目的有用的已经存在的“盛载”和“包装类”任何内存分配。 例如:

 std::vector<int> arr;

将工作作为整数变量的存储,你永远不用担心释放内存,或者甚至不知道你需要多少你已经有存储在他们面前。

 std::shared_ptr<int> arr = new int[num]; 

另一种情况下,如果当“shared_ptr的”是不再使用[它追踪共享的指针类里面,所以你永远需要关心释放内存。

[1]如果你不想内存泄漏,并且它的“不良作风”内存泄漏。 不做,如果你做的任何人开心。



Answer 2:

我已经看到了关于内存分配在C ++中很多帖子,关于“新的运营商”与“运营商新的”的问题,有关问题new int(100) VS new int[100]有关内存初始化的问题......我认为应该有汇总清楚一劳永逸,而我选择了这个问题写这个总结的一切答案。 它是关于动态内存分配,在运行时堆分配。 我也提供了一个简要的实现 (公共领域)。


çVS C ++

动态内存分配主要功能:

  • 在C(报头<cstdlib>我们有主要malloccallocfree 。 我不会谈论realloc
  • 在C ++(报头<new> ),我们有:
    • 模板单个对象的分配与初始化参数:
      • new T( args )
      • new (std::nothrow) T( args )
      • delete ( T* )
    • 模板多个对象的默认初始化分配:
      • new T[ size_t ]
      • new (std::nothrow) T[ size_t ]
      • delete[] ( T* )
    • 模板存储器初始化不分配单个或多个对象:
      • new (void*) T( args )
      • new (void*) T[ size_t ]
    • 内部新表达式
      • 原始内存分配::operator new( size_t ) ;
      • 原始内存分配无一例外::operator new( size_t, std::nothrow ) ;
      • 原始内存初始化不分配::operator new( size_t, ptr )

请看看这篇文章的简要比较。


传统C动态分配

要点 :完整类型擦除( void*指针),并且因此没有施工/破坏 ,以字节为单位指定的(通常使用大小sizeof )。

malloc( size_t )在所有未初始化的内存(原始内存装着垃圾,总是使用前手动初始化)。 calloc( size_t, size_t )初始化所有的位为0(少量的开销,但对于POD的数字类型是有用的)。 任何分配的内存应该用发行free ONLY。

类实例的建筑/销毁应手动完成使用 / 释放内存。


C ++动态分配

要点 :混淆,因为类似的语法做不同的事情, 所有的 delete -statements调用析构函数, 全部 delete -statements采取完全类型指针, 一些 new -statements返回全类型指针, 一些 new -statements调用一些构造函数。

警告 :你会看到下面, new可以是一个关键字功能 。 最好不要谈“新的运营商”和/或“运营商新的”,以避免混乱 。 我称之为“ new -statements”包含任何有效的语句new无论是作为一个函数或关键字。 人们也谈“ new -expressions”,其中new的关键字,而不是功能。

原始内存分配(不初始化)

不要将此自己使用。 这是由新的表达式内部使用(见下文)。

  • ::operator new( size_t )::operator new( size_t, std::nothrow )采取大小的字节数,并返回一个void*在成功的情况下。
  • 在失败的情况下,前者抛出一个异常std::bad_alloc ,后者返回NULL
  • 使用::operator new( sizeof(T) )为类型的单个对象T (和delete发布),和::operator new( n*sizeof(T) )多个对象(和delete[]为释放)。

这些分配没有初始化的内存,尤其是,他们叫上分配对象的默认构造函数。 因此, 必须初始化所有你使用释放之前手动分配任何元素 deletedelete[]

:我不能强调不够,你不应该使用这个自己。 如果你要使用它,但要确保你传递一个指针void调用既可以当的,而不是一个类型的指针deletedelete[]随时手动初始化后)这种分配。 我亲身经历的运行时错误与非POD类型在某些编译(也许我的错误)。

原始内存初始化(不分配)

不要将此自己使用。 这是由新的表达式内部使用(见下文)。 在下文中,我假定void *ptr = ::operator new( n*sizeof(T) )对于某些类型T和大小n

然后::operator new( n*sizeof(T), (T*) ptr )初始化n类型的元素T从开始ptr使用默认构造T::T() 没有分配这里,只使用默认的构造函数初始化。

单对象分配和初始化

  • new T( args )分配用于类型的单个对象初始化存储器T使用构造T::T( args ) 。 默认构造函数将不会被调用,除非参数被忽略(即new T()甚至new T )。 抛出异常std::bad_alloc失败。
  • 同为new (std::nothrow) T( args )不同的是它返回NULL失败的情况下。
  • 使用delete调用析构函数T::~T()和释放相应的内存。

多对象分配和初始化

  • new T[n]分配用于初始化存储器n类型的对象T使用默认构造。 抛出异常std::bad_alloc失败。
  • 同上为new (std::nothrow) T[n]不同之处在于它返回NULL在故障的情况下。
  • 使用delete[]到调用析构函数T::~T() 的每个元素 ,并释放相应的存储。

内存初始化(又名“新位置”)

这里没有分配。 无论分配是怎么做的:

  • new (ptr) T(args)调用构造函数T::T(args)上存储在存储ptr 。 默认构造函数不被执行,除非被省略参数。
  • new (ptr) T[n]调用默认构造T::T()n类型的对象T从存储ptrptr+n (即, n*sizeof(T)个字节)。

相关文章

  • 简明比较新/删除VS的malloc /免费
  • 更详细的malloc VS新 ,看@Flexo的答案
  • 新的运营商VS运营商新的 ,避免不使用这些术语的混乱


文章来源: What is Dynamic Memory Allocation in C++?