4

我正在尝试使用参数作为全局的 operator new 来实现。如果没有 args 的 new 重载没有问题,但是在尝试编译时出现以下错误

inline void* operator new(size_t, void* p) {
    //...
    return p;
}

c:\bjarne_exercise_6.cpp(14): error C2084: function 'void *operator new(size_t,void *) throw()' has a body c:\program files\microsoft visual studio 10.0\vc\include\new( 55) : 见之前对“新”的定义

c:\bjarne_exercise_6.cpp(40): error C2264: 'operator new' : 函数定义或声明错误;未调用函数

我刚刚解决了这个问题,你必须在 #include stdafx.h 之前声明这个 不,不是真的。它编译得很好,但仍然没有调用这个函数,而是来自新头文件的版本。之所以如此,是因为新标头中已经定义了新位置(带有 2 个参数)。普通的 new (只有 1 个 size_t 参数)只在那里声明,所以你仍然可以重载它。因此,如果您想要具有超过 1 个参数的特殊新参数,则以下 @trion 建议的解决方案是合适的。

4

4 回答 4

5

这种放置形式operator new(正如标准所称的那样)已经在全局命名空间中的 C++ 程序中定义,您不能自己在那里提供定义。与其他 global 不同operator new,这个是不可替换的。

于 2012-08-22T11:40:37.980 回答
3

C++ 标准在头文件中定义了operator new一个额外的位置。它的实现类似于这样:void*<new>

void* operator new(size_t, void* m)
{
    return m;
}

它通常用于在已分配的内存上实例化对象,例如通过将分配与实例化分开的 STL 容器。因此,如果您包含任何取决于 的标准标题<new>,则将已经定义了新的展示位置。

如果您想创建自己的operator new具有不同语义的版本,可以使用虚拟参数来消除歧义:

struct my_new_dummy {} dummy;
void* operator new(size_t, my_new_dummy, void* m);

//...

int mem;
int* ptr = new(dummy, &mem) int;

编辑:您可以重新定义普通operator new但不能重新定义新位置的原因是前者默认由编译器定义并且可以手动覆盖,而新位置定义在标头中,因此与您的重新定义发生冲突.

于 2012-08-22T11:45:00.050 回答
3

1)您有编译错误,因为无法替换全局级别放置新运算符!请参阅 c++ 11 标准(在以前的标准中也是如此)。

18.6.1.3 Placement forms [new.delete.placement]
1 These functions are reserved, a C++ program may not define functions that 

替换标准 C++ 库 (17.6.4) 中的版本。(3.7.4) 的规定不适用于 operator new 和 operator delete 的这些保留放置形式。void* operator new(std::size_t size, void* ptr) noexcept;

所以基本上你可以替换其他全局 new 运算符(见下文),但不能替换标准禁止的放置形式!

void* operator new (std::size_t size) throw (std::bad_alloc) 

2)另一方面,您可以编写自己的类级别新运算符,包括在您的类中放置新运算符,没关系:

class Test
{
public:

    void* operator new (std::size_t size) throw (std::bad_alloc) {
        return malloc(size);
    }

    void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw() {
        return malloc(size);
    }

    void* operator new (std::size_t size, void* ptr) throw() {
        return malloc(size);
    }
};
于 2012-10-16T14:37:27.307 回答
1

是的。的这种放置形式operator new已经在全局命名空间中定义,因此您不能自己在那里提供定义。这是不可更换的。

于 2013-04-24T19:13:41.077 回答