operator new已经有了一个正文

时间:2012-08-22 11:34:24

标签: c++ operators new-operator

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

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

c:\ bjarne_exercise_6.cpp(14):错误C2084:函数'void * operator new(size_t,void *)throw()'已经有一个正文             c:\ program files \ microsoft visual studio 10.0 \ vc \ include \ new(55):参见先前对'new'的定义

     

c:\ bjarne_exercise_6.cpp(40):错误C2264:'operator new':函数定义或声明中的错误;功能未被称为

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

4 个答案:

答案 0 :(得分:5)

operator new的放置形式(标准称之为)已在全局命名空间的C ++程序中定义,您无法自己提供定义。与其他全局operator new不同,这个不可替换。

答案 1 :(得分: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;

所以基本上你可以替换另一个全局新运算符(见下文),但作为标准的放置形式禁止它!

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);
    }
};

答案 2 :(得分:2)

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但不重新定位新的原因是前者默认由编译器定义并且可以手动覆盖,而放置新的在标题中定义,因此导致与重新定义冲突。

答案 3 :(得分:1)

是肯定的。 operator new的此放置形式已在全局命名空间中定义,因此您无法自己提供定义。这是不可替换的。