4pie0
4pie0

Reputation: 29724

operator new already has a body

I am trying to implement operator new with parameter as global. There is no problem if new without args is overloaded, but I get followings errors when trying to compile

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()' already has a body c:\program files\microsoft visual studio 10.0\vc\include\new(55) : see previous definition of 'new'

c:\bjarne_exercise_6.cpp(40): error C2264: 'operator new' : error in function definition or declaration; function not called

I have just solved this, you have to declare this before you #include stdafx.h No, not true. It compile well but still not this function is called but the version from new header file. It is so, because placement new(with 2 params) is already defined in new header. The ordinary new (with just 1, size_t parameter) is only declared there, so you can still overload it. So if you want special new with more than 1 parameter the solution suggested by @trion below is appropriate.

Upvotes: 4

Views: 4217

Answers (4)

RoundPi
RoundPi

Reputation: 5947

1) You have the compile error because global level placement new operator cannot be replaced ! See c++ 11 standards(in previous standards as well).

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

displace the versions in the Standard C++ library (17.6.4). The provisions of (3.7.4) do not apply to these reserved placement forms of operator new and operator delete. void* operator new(std::size_t size, void* ptr) noexcept;

So basically you can replace the other global new operator(see below), but NOT the placement form as the standards forbid it !

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

2) On the other hand, you can write your own class level new operators including the placement new one inside your class, that's ok:

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

Upvotes: 3

user2316968
user2316968

Reputation:

yes. This placement form of operator new is already defined in a global namespace, so that you cannot provide a definition there yourself. This is not replaceable.

Upvotes: 1

Fabian Knorr
Fabian Knorr

Reputation: 3184

The C++ standard defines a placement operator new taking an additional void* in the header file <new>. Its implementation is similar to this:

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

It's commonly used to instantiate objects on already allocated memory, e.g. by STL containers which separate allocation from instantiation. So if you include any standard header depending on <new>, the placement new will already be defined.

If you want to create your own version of operator new with different semantics, you can use a dummy parameter to disambiguate the situation:

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

//...

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

Edit: The reason why you can redefine the ordinary operator new but not placement new, is that the former is by default defined by the compiler and can be overridden manually, whereas placement new is defined in a header, therefore causing a conflict with your re-definition.

Upvotes: 3

Luc Danton
Luc Danton

Reputation: 35449

This placement form of operator new (as the Standard calls it) is already defined in a C++ program in the global namespace, you cannot provide a definition there yourself. Unlike other global operator news, this one is not replaceable.

Upvotes: 5

Related Questions