使用参数构造函数模拟 new[]
如果我没有修改参数构造函数内的任何static
变量,则低于模拟new T[N] (x,y);
(带参数的数组new)的正确方法)?
template<typename T>
void* operator new [] (size_t size, const T &value)
{
T* p = (T*) malloc(size);
for(int i = size / sizeof(T) - 1; i >= 0; i--)
memcpy(p + i, &value, sizeof(T));
return p;
}
用法将是,
struct A
{
A () {} // default
A (int i, int j) {} // with arguments
};
int main ()
{
A *p = new(A(1,2)) A[10]; // instead of new A[10](1,2)
}
If I am not modifying any static
variable inside the argument constructor, is below the proper way to simulate new T[N] (x,y);
(array new with arguments) ?
template<typename T>
void* operator new [] (size_t size, const T &value)
{
T* p = (T*) malloc(size);
for(int i = size / sizeof(T) - 1; i >= 0; i--)
memcpy(p + i, &value, sizeof(T));
return p;
}
Usage will be,
struct A
{
A () {} // default
A (int i, int j) {} // with arguments
};
int main ()
{
A *p = new(A(1,2)) A[10]; // instead of new A[10](1,2)
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我建议
我意识到这并不能真正解决数组的问题。
您可以使用,
因为该标准保证连续存储。不过,调整向量大小时要非常小心,因为它可能会使 p 无效,
我检查了 boost::array<> (它适应 C 风格数组),但它没有定义构造函数......
I'd suggest
I realize that this doesn't really address the question for arrays.
You could use
since the standard guarantees contiguous storage. Be very careful with resizing the vector though, because it could invalidate p
I checked boost::array<> (which adapts C style arrays), but it doesn't define constructors...
这不行。您将对象复制到未初始化的内存中,而没有调用正确的复制语义。
只要您只使用 POD,就可以了。但是,当使用不是 POD 的对象(例如您的
A
)时,您需要采取预防措施。除此之外,
operator new
不能以这种方式使用。正如 Alexandre 在评论中指出的那样,该数组将无法正确初始化,因为 C++ 将调用所有的构造函数调用你的operator new
之后的元素,从而覆盖这些值:这会产生:
……不是期望的结果。
This isn’t OK. You are copying objects into uninitialised memory without invoking proper copy semantics.
As long as you’re only working with PODs, this is fine. However, when working with objects that are not PODs (such as your
A
) you need to take precautions.Apart from that,
operator new
cannot be used in this way. As Alexandre has pointed out in the comments, the array won’t be initialised properly since C++ will call constructors for all elements after having called youroperator new
, thus overriding the values:This yields:
… not the desired outcome.
这是不行的 - 如果
typename T
有这样的对象(您的示例中的struct A
确实有一个),C++ 将调用这些对象的非平凡默认构造函数,这将导致重建对象内存中已被占用。适当的解决方案是使用 std::vector (推荐)或调用
::operator new[]
来分配内存,然后使用placement-new调用构造函数并注意例外情况(如果有)。That's not okay - C++ will call those objects non-trivial default constructors if
typename T
has such (struct A
in your example does have one) and that would lead to reconstructing objects in memory already occupied.An appropriate solution would be to use
std::vector
(recommended) or call::operator new[]
to allocate memory, then call constructors using placement-new and taking care of exceptions if any.您应该考虑到可能会调用
operator new[]
,要求比裸露的sizeof(T) * n
更多的内存。可能需要这个额外的内存,因为 C++ 必须知道在
delete[] p;
的情况下要销毁多少对象,但它无法可靠地使用new p[sz 分配的内存块的大小]
来推断这个数字,因为内存可能已被请求给自定义内存管理器,因此(例如您的情况)无法仅通过知道指针来知道分配了多少内存。这也意味着您尝试提供已初始化的对象将会失败,因为返回到应用程序的实际数组可能不会从您从自定义
operator new[]
返回的地址开始,因此初始化可能会错位。You should consider that
operator new[]
may be called asking for more memory than the bare amountsizeof(T) * n
.This extra memory is possibly needed because C++ must know how many object to destroy in case of
delete[] p;
but it cannot reliably use the size of block of memory allocated bynew p[sz]
to infer this number because the memory may have been asked to a custom memory manager so (e.g. your case) there is no way to know how much memory was allocated only by knowing the pointer.This also means that your attempt to provide already-initialized objects will fail because the actually array returned to the application will potentially not start at the address you returned from your custom
operator new[]
so that initialization could be misaligned.destroyArray 也可以这样写,具体取决于您构建的平台:
destroyArray could also be written like this depending on the platform you are building for: