在移动/复制c ++对象实例时

dua*_*ane 5 c++

我试图在C++中创建一个类型不可知的向量,它由两个东西区分.首先,它在对象本身中分配内存,至少在某个点之前,而不是在堆上维护实际的对象数组.其次,它不能使用C++的复制/分配构造函数,这似乎会减慢代码速度并且不是必需的.

在查看我在计算机上维护的代码库时,我在LLVM的代码库中找到了一个类,它非常完美地描述了我正在寻找的内容:SmallVector.h.作为C++的新手,我不完全确定为什么会做出一些设计决策.例如,为什么分配数组U而不是T?评论给出了一个线索:

如果T有一个ctor或dtor,我们不希望它自动运行,所以我们需要将空间表示为其他东西.一个char数组可以很好地工作,但可能没有充分对齐.相反,我们为空间使用了一些联合实例,这保证了最大的对齐.

U当然,指的是以下联盟:

union U {
    double D;
    long double LD;
    long long L;
    void *P;
} FirstEl;
Run Code Online (Sandbox Code Playgroud)

所以,我想,这是我真正的问题:为什么要分配一个T暗示构造函数/析构函数被调用的数组?有没有办法在不调用这些构造函数/析构函数的情况下移动c ++对象实例,即进出向量?我想我可以使用LLVM的SmallVector实现,但我讨厌使用代码而不理解它.

最好的,杜安

Ker*_* SB 3

您应该查看标准库分配器背后的基本机制,它可以解决您可能遇到的许多问题!

这是基本的分配原则。我们将内存分配和对象构造分开。正如您所观察到的,最大的障碍是内存应该针对对象正确对齐:

// getting memory
void * p = malloc(1000);  // version 1, system's allocator
char q[1000];             // automatic array, this is also memory :-)

// constructing an object
T * m_x1 = ::new (p) T;   // default-initialized
T * m_x2 = ::new (q) T(); // value-initialized
T * m_x3 = ::new (q + sizeof(T)) T(1, 'a'); // some specific constructor

// destroying the objects:
m_x1->~T();
m_x2->~T();
m_x3->~T();
Run Code Online (Sandbox Code Playgroud)

为了实现您的想法,您可以采用q我使用的 char 数组并将其作为您的类的成员。也就是说,类总是带有一些用于构造对象的内存。

实际的对象构造是通过全局placement-new 表达式完成的。回想一下,这样构造的对象必须手动销毁(这将是你的责任)。

标准库分配器几乎做了类似的事情。

分离内存分配和对象构造是任何高级内存管理、责任拥有类的核心。

请注意,一旦在特定地址构造了对象,就不得随意移动内存。该对象很可能取决于它自己在内存中的位置!移动对象的唯一有效方法是复制/移动构造一个新对象。