数组分配 - 你可以停止调用构造函数和析构函数吗?

时间:2011-02-11 17:03:06

标签: c++

我处于不幸的位置,编写自己的矢量实现(不,很遗憾,使用标准实现是不可能的)。现在使用的那个使用原始字节缓冲区和就地构造和对象的解构,但作为副作用,我无法查看实际元素。所以我决定做一个使用内部真实数组的变体实现。

在处理它时,我注意到分配数组会导致额外调用construtor和析构函数,并将其映射到原始缓冲区版本。在不丢失阵列访问权限的情况下,这种开销是否可以避免?如果它与原始缓冲区版本一样快,那就太好了,所以可以替换它。

如果有人知道一个很好的实现方式我也可以自己开发,或者至少从中得到一些想法,我也很感激。毕竟这项工作非常棘手。 :)

编辑:

一些代码可以更好地解释它。

T* data = new T[4]; // Allocation of "num" elements
data[0] = T(1);
data[1] = T(2);
delete[] data;

现在,对于数组的每个元素,都调用了默认构造函数,然后调用了2个赋值方法。因此,只有2个构造函数调用,我们有4个和后来的4个析构函数调用,而不是2个。

3 个答案:

答案 0 :(得分:2)

  

作为副作用,我无法查看实际的元素。

为什么不呢?

void* buffer = ...
T* elements = static_cast<T*>(buffer);
std::cout << elements[0] << std::endl;

答案 1 :(得分:2)

使用true数组意味着将调用构造函数。你需要转到原始字节缓冲区 - 但这并不算太糟糕。假设你有一个缓冲区:

void *buffer;

将其更改为T *

T *buffer;

分配时,将其视为原始内存缓冲区:

buffer = (T *) malloc(sizeof(T) * nelems);

并根据需要调用构造函数:

new(&buffer[x]) T();

您的调试器应该能够像使用真实数组一样查看缓冲区的元素。当需要释放数组时,当然,你有责任释放数组的元素,然后将其传递给free()

for (int i = 0; i < nInUse; i++)
    buffer[x].~T();
free((void*)buffer);

请注意,我不会使用new char[]delete[]来分配此数组 - 我不知道new char[]是否会正确对齐,无论如何您需要在char*数组之前,请小心转回delete[]

答案 2 :(得分:1)

我发现以下实现非常有趣:C Array vs. C++ Vector

除了性能比较之外,他的矢量实现还包括向量上的推/弹操作。

The code还有一个显示如何使用宏的示例:

#include "kvec.h"
int main() {
    kvec_t(int) array;
    kv_init(array);
    kv_push(int, array, 10); // append
    kv_a(int, array, 20) = 5; // dynamic
    kv_A(array, 20) = 4; // static
    kv_destroy(array);
    return 0;
}