c++ - ::operator new[] 和我的自定义容器的分配

c++ - ::operator new[] and allocation for my custom container

我遇到了一个无法解决的问题。 我正在编写自己的容器,它或多或少类似于 std::vector<T>,但我不知道如何解决为对象分配内存的问题。

举例来说,我围绕一个数组编写了一个包装器,并希望像这样分配数据:

T* cArray = new T[size];
cArray[index] = std::move(obj);

如果 obj 没有不接受任何参数的默认构造函数,我会得到一个错误:"Class: no appropriate default constructor available".

所以我虽然可以通过不使用 operator new 调用 obj 的构造函数来解决问题:static_cast<T*>(::operator new(sizeof(T)*this->cap)) 并且只有当我使用 int, double and floats 等内置类型作为我的测试成员时才有效对象

如果我这样做:

struct Test
{
    Test(int x){}
    std::string s;
    double d;
}

MyVector<Test> vec;
vec.push_back(Test(1));

如果我尝试将数据分配到包含以下行的 push_back 函数中的位置,我会收到运行时错误:

cArray[index] = std::move(obj);

在文件中:xmemory0 第 106 行:

Expression: "(_Ptr_user & (_BIG_ALLOCATION_ALIGNMENT -1)) == 0

同样,这只是当我不使用内置类型时才会出现的问题。如果我删除 std::string 作为成员,一切都会按预期进行。我不知道问题的原因可能是什么,也不知道经过数小时的搜索后如何解决。

你们知道怎么解决这个问题吗?

这才是分配内存的正确方式。但是您最终仍然需要调用构造函数,将空字节转换为对象。 (稍后您需要调用析构函数。)

您需要使用 "placement new" 来调用构造函数:

new (&carray[index]) Test(obj)

你的想法是对的,至少是前半部分。即分配原始内存,而不是使用new Test[N]。但是你仍然需要构造你的对象,你可以使用 placement new 来完成。给定一个指针 p,它指向你想要构造对象的位置,你可以这样做:

new (p) Test(...constructor args...);

另请注意,当您使用完对象后,您将需要手动调用析构函数:

p->~Test();

一个答案是不存储 T[] 而是存储相同大小和对齐要求的东西(最常见的选择是 aligned_storage). Then you use the placement new 运算符在其中构造项目,例如

new (&carray[index]) T(...args)

完成项目后,您需要手动调用每个项目的析构函数。