分配但不构造大量的C ++对象

时间:2016-10-12 23:11:32

标签: performance optimization constructor c++14 large-data

在某些情况下,我的C ++ 14程序需要大约1亿std::vector的“块”,这需要接近1 GB的RAM。我们可以安全地假设所需的内存可用。

但是,分配新的calloc()非常慢,因为复杂的构造函数被称为1亿次。在我的机器上,代码需要大约一整秒来初始化数组。

通过比较,调用malloc,将分配的内存初始化为零,效果大致相同,将在很短的毫秒内运行。

事实证明,我们甚至不需要这种初始化,因为大型阵列中的复合体将很快从外部源填充。因此,我希望将“块”中对象的构造推迟到以后的时间,然后直接从外部数据源构建它们。

所以我的问题是,是否有一种安全的惯用和高效的C ++方法,或许沿途使用C ++移动语义?如果没有,我们决定简单地reinterpret_cast内存块,那么我们可以简单complex<float>将内存块Gridview转换为普通的C数组吗?

感谢您的帮助

Jean-Denis Muys

3 个答案:

答案 0 :(得分:3)

如果将complex<float>类的默认构造函数定义为空,这会使成员变量保持未初始化,那么在打开编译器优化的情况下,两个操作之间不应该有任何真正的区别。

假设complex类的以下定义。

template <typename T>
struct complex
{
  complex() {}; // Empty constructor does nothing
  T a, b;
};

在x86-64 gcc 6.2和-O2启用时使用vector初始化生成的程序集是:

std::vector<complex<float>> v(100);

    mov     edi, 800
    call    operator new(unsigned long)
    mov     rdi, rax
    call    operator delete(void*)

生成的用于手动调用mallocfree的程序集为:

auto v = malloc(100 * sizeof(complex<float>));
free(v);

    mov     edi, 800
    call    malloc
    mov     QWORD PTR [rsp+8], rax
    mov     rdi, QWORD PTR [rsp+8]
    call    free

如您所见,vector实现不再为每个元素调用complex<float>的构造函数。 vector的使用更加正确和可读,并且还利用了有助于防止内存泄漏的RAII。

答案 1 :(得分:2)

我强烈建议坚持使用c ++并避免自己手动管理内存。

标准库应该足够了。 E.g。

std::vector< complex > my_vector;

// Reserve the necessary space without constructing anything
my_vector.reserve( 100'000'000); 

// construct the elements when needed
populate( my_vector ); 

答案 2 :(得分:0)

所以你的问题是你是否可以使用malloc()。多年前,我使用与旧的C ++编译器相同的方法,并且它工作正常。但最后我不得不拨打free()而不是delete[]。我认为这是特定于实现的,因此您应该在编译器上尝试它。