【问题标题】:Memory allocation for objects in arrays数组中对象的内存分配
【发布时间】:2020-06-02 17:35:00
【问题描述】:

这是我的代码 [注意我注释了 cstr 和析构函数]

#include <iostream>
#include <stdlib.h>
#include <array>

class MyIntClass
{
    int _mymember;

  public:  

// MyIntClass(){}
// ~MyIntClass(){}

void *operator new(size_t size)
{
    std::cout << "new: Allocating " << size << " bytes of memory" << std::endl;
    void *p = malloc(size);

    return p;
}
void operator delete(void *p)
{
    std::cout << "delete: Memory is freed again " << std::endl;
    free(p);
}


void *operator new[](size_t size)
{
    std::cout << "new: Allocating " << size << " bytes of memory" << std::endl;
    void *p = malloc(size);

    return p;
}

  void operator delete[](void *p)
    {
        std::cout << "delete: Memory is freed again " << std::endl;
        free(p);
    }
};

void line(){
        std::cout << "\n--------------------------------------------------\n" << std::endl;
}

int main()
{
    line();
    std::cout << "Using new overloading and malloc\nWe will create one object of MyIntClass that is supposed to be 4 bytes" << std::endl;
    MyIntClass *m1 = new MyIntClass();

    line();
    //I want to create an array of the MyIntClass of two objects
    std::cout << "Now we create array of MyIntClass using <array> header" << std::endl;
    std::array<MyIntClass, 2> z = {};

    std::cout << " The elements in the array z = "<< z.size() <<std::endl;

    std::cout << "The memory allocated for  array z = " << sizeof(z) << std::endl;

    line();

    std::cout << "\nNow we create array using new[] overloading and malloc " << std::endl;

    MyIntClass *i = new MyIntClass[2]();
    delete[] i;
}

现在结果如下:


使用新的重载和 malloc
我们将创建一个 MyIntClass 对象,它应该是 4 个字节

新:分配 4 个字节 记忆


现在我们使用 &lt;array&gt; header 创建 MyIntClass 数组
数组中的元素 z = 2
为数组 z = 8 分配的内存


现在我们使用 new[] 重载和 malloc 创建数组
新:分配 8 个字节的内存

对于没有经验的 C++ 程序员来说,我认为每件事都按预期工作

现在如果我取消注释构造函数,同样的结果会发生

但是,当我取消注释析构函数时,会出现不同的结果

现在我们使用 new[] 重载和 malloc 创建数组
新:分配 12 字节内存

所以我的问题是对此有何解释: 在使用array 库或重载new[] 和malloc 的两种方法中,创建两个对象的数组,每个对象都是4 字节,将导致为数组分配8 字节的内存。

然而,当我们有一个对象的析构函数时,malloc 将为这个 2 个元素的数组分配 12 个字节而不是 8 个字节。

我看到了这个question on SO,但它没有解释我的情况

以下是我的编译器版本:

gcc 版本 8.2.0 (MinGW.org GCC-8.2.0-3)

【问题讨论】:

  • 删除所有这些多余的空行将使您的代码更具可读性 — 无需对实际代码进行任何更改!
  • 什么是“memalloc”?
  • 程序的行为是不确定的,因为你在一个不是由new返回的指针上使用了delete(它是由new[]返回的)。
  • 尝试打印出sizeof(MyIntClass) 用于您的各种类配置。
  • @Yksisarvinen 否。使用delete[] 以外的任何内容来释放分配有new[] 的指针具有未定义的行为。不管是否有重载的运算符。

标签: c++ arrays memory-management


【解决方案1】:

额外分配内存的原因是编译器需要知道数组中元素的数量,以便在您调用delete[] 时能够对数组的每个元素调用析构函数。对于一般可破坏的类型,编译器不需要调用析构函数,因此不需要额外的数组大小空间。

【讨论】:

  • 您说“编译器需要知道数组中元素的数量才能调用析构函数”,但是这里std::array&lt;MyIntClass, 2&gt; z = {};和MyIntClass *i = new MyIntClass[2]();已经指定了数量;那么为什么分配的空间是不同的,尽管我们在编译时指定了元素的数量而不是运行时?我还是一头雾水,谢谢你的回复
  • std::array(和 C 样式数组)不会动态分配内存。数组的大小总是N * sizeof(T),其中 N 在编译时是已知的,不需要单独存储。重要的部分是编译器在销毁数组时静态知道 N。 OTOH,当您调用operator new[] 时,元素的数量是运行时值(即使您将其指定为常量),无法从返回的指针中推断出来。该运行时值需要存储在某处,以便operator delete[] 能够调用析构函数。
猜你喜欢
  • 2013-12-04
  • 2012-05-04
  • 1970-01-01
  • 2021-07-24
  • 2015-10-15
  • 2020-05-23
  • 2017-05-13
  • 1970-01-01
相关资源
最近更新 更多