指针连续记忆的指针

时间:2012-01-07 04:18:10

标签: c++ pointers memory-management

考虑以下代码

struct foo
{
    const int txt_len;
    const int num_len;

    char * txt;
    int * num;

    foo(int tl, int nl): txt_len(tl), num_len(nl)
    {
        char * tmp = new char[txt_len * sizeof(char) + num_len * sizeof(int)];

        txt = new (tmp) char [txt_len * sizeof(char)];
        num = new (tmp + txt_len * sizeof(char)) int[num_len * sizeof(int)];

        // is this the same as above?
        // txt = tmp;                                  
        // num = (int *) (tmp + txt_len * sizeof(char));
    }

    ~foo()
    {
        delete[] txt; // is this the right way to free the memory?
    }
};

我希望*txt*num是连续的,这是最好的方法吗?

放置新算法和指针算术有什么区别吗?我应该使用哪一个?

5 个答案:

答案 0 :(得分:1)

如果你想要一个连续的内存块,你必须通过一次调用operator new[]malloc()或类似内容来分配它。对这些函数的多次调用不保证分配块的任何连续性。您可以根据需要分配一个大块,然后从中雕刻零件。

你应该deletefree()之前用newmalloc()分配的所有块,否则你会泄漏内存并可能使你的程序不稳定(它会失败)在某些时候分配更多内存)并对操作系统中的内存施加不必要的压力,可能会减慢其他程序的速度或使其不稳定。

然而,Placement new实际上并没有分配任何内存。它只是在指定位置构造一个对象,因此您不需要释放该内存两次。

我在您的代码中看到的一个问题是它没有对齐整数。在某些平台上,读取或写入内存大于1字节的整数必须对齐,如果不是,则可以从/向错误位置读取/写入值,或者获取CPU异常导致程序终止。 x86在这方面是非常宽容的,并不介意,但可能会因性能下降而对您征税。

答案 1 :(得分:1)

由于对齐问题,您需要先将int数据放入。但是我们不能因为类型错误而执行delete num[] - 必须在删除之前将其强制转换为char*

char * tmp = new char[num_len * sizeof(int) + txt_len * sizeof(char)];

num = new (tmp) int[num_len];
txt = new (tmp + num_len * sizeof(int)) char [txt_len];

(这可以自由地使用sizeof(char)==1

这一事实

您可能想要delete[] num,但num的类型为int*newchar*。所以你需要这样做;

delete[] (char*) num;

答案 2 :(得分:0)

只要您使用POD类型,这是相同的。你的删除没问题 但是,正如大卫的评论所述,你需要考虑对齐问题。

答案 3 :(得分:0)

当你想在一些预先分配的内存块上调用class / struct的构造函数时,主要使用Placement new。

但是对于原生类型来说,使用贴片新品并没有什么不同。指针算术。

如果我错了,请纠正我。

答案 4 :(得分:0)

如果txt和num总是指向int和char,其他内置类型或其他类型不需要构造,那么没有。您不需要新的展示位置。

另一方面,如果您要将其中一个更改为需要构造的类,即将txt更改为类型std :: string,则必须使用placement new。

Placement new允许您调用构造函数,如果您愿意,可以构建该地址的对象。内置类型具有默认构造函数,如果不进行初始化,则不执行任何操作。

在这两种情况下,你需要做指针运算,只需要一种方法将答案存储在指针中,另一种方法是将答案传递给placement new,它将它返回给你存储在指针中,然后调用构造函数