我正在编写一个重载版本的放置新,并希望在函数中初始化一个整数数据成员。
#include <cstdlib>
#include <new>
struct A {
int i;
void* operator new(size_t, void *p, int x) { return p; }
};
int main() {
A* pa = new(malloc(sizeof(A)), 10) A;
pa->~A();
delete pa;
}
我想知道如何在上面的代码中做到这一点。也
class A {
public:
static int* p;
void* operator new(size_t sz, unsigned int val) {
p = (int*) malloc(sizeof(val));
*p = val;
}
};
int* A::p;
int main() {
A *p= new (10) A(); // calls overloaded new with initialization and not placement new
cout << *(p->p) << endl; // Ans: 10
}
在上面的代码中,语法看起来类似于放置新,但它调用重载的新版本。那么编译器如何区分重载放置 new 和运算符 new?这是基于参数类型(即)void*吗?如果有一个 void* 的数据成员,并且应该通过 void* 参数对其进行初始化,该怎么办?编译器如何处理这个问题?
那么编译器如何区分重载放置 new 和运算符 new?
其实不然。放置新表达式使用与放置参数匹配的参数调用 operator new
重载(如果存在此类重载)。所以标准放置新
new (p) A;
调用在 <new>
中声明的重载
void* operator new(size_t, void*);
而具有不同参数类型的表达式会调用重载,因为类型匹配。
这是基于参数类型(即)
void*
吗?
是的,这正是它的工作原理。
如果有一个
void*
的数据成员并且应该通过void*
参数初始化它怎么办?
数据成员应由构造函数初始化,而不是operator new
。只有在初始化对象之前控制内存的分配方式时,才应覆盖operator new
。
不要这样做。放置(如"额外参数",而不是"无实际分配")new
用于分配内存。初始化是构造函数的用途。
尽管奇怪且不太可能,但从技术上讲,C++ 实现没有理由不能包含擦除新实现返回的内存区域的代码,然后再初始化该区域中的对象。它可以将其擦除为"全零"或一些调试位模式。