使用数据成员初始化和与普通new运算符的差异来重载放置new运算符

时间:2014-02-27 07:50:10

标签: c++

我正在编写placement new的重载版本,并希望初始化函数内的整数数据成员。

#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
}

在上面的代码中,语法看起来类似于placement new,但是它调用了重载的新版本。那么编译器如何区分重载的placement new和operator new呢?这是基于参数类型(即)void *?如果有一个数据成员是void *并且应该通过void *参数初始化该怎么办?编译器如何处理这个?

2 个答案:

答案 0 :(得分:4)

  

那么编译器如何区分重载的placement new和operator new?

没有。 placement-new表达式调用operator new的重载,其参数与放置参数匹配(如果存在这样的重载)。所以标准放置新

new (p) A;

调用<new>

中声明的重载
void* operator new(size_t, void*);

而你的表达式使用不同的参数类型调用你的重载,因为类型匹配。

  

这是基于参数类型(即)void*吗?

是的,这正是它的工作原理。

  

如果数据成员为void*并且应该通过void*参数初始化该怎么办?

数据成员应该由构造函数初始化,而不是operator new。如果要在初始化对象之前控制内存的分配方式,则只应覆盖operator new

答案 1 :(得分:1)

不要这样做。放置(如“额外参数”,而不是“无实际分配”)new用于分配内存。初始化是构造函数的用途。

虽然很奇怪且不太可能,但在技术上没有理由说C ++实现不能包含在初始化该区域中的对象之前擦除新实现返回的内存区域的代码。它可以将其擦除为“全零”或一些调试位模式。