How could I sensibly overload placement operator new?
Asked Answered
G

9

22

C++ allows overloading operator new - both global and per-class - usual operator new, operator new[] used with new[] statement and placement operator new separately.

The former two of those three are usually overloaded for using customized allocators and adding tracing. But placement operator new seems pretty straightforward - it actually does nothing inside. For example, in Visual C++ the default implementation just returns the address passed into the call:

//from new.h
inline void* operator new( size_t, void* where )
{
   return where;
}

What else could it do? Why and how could I sensibly overload placement operator new?

Glycogenesis answered 9/9, 2010 at 8:47 Comment(8)
Are you asking for uses of overloading the new operator? That's a pretty broad question.Gagne
@Alexander Rafferty I'm asking specifically about uses of overloading placement new. I can't see any purpose in this specific case.Glycogenesis
+1 for getting into the header files.Gloaming
+1, interesting question, that's why I like SO :)Graphics
Pedantically: You don't overload operator new, you replace it (or override it). Overloading means creating a new method/function using the same name as an existing one but with a different signature. When replacing a function, you use the identical signature.Pergola
@0xbaadf00d What’s the purpose of your comment? If you have any additional info to this question, post a link! If it’s just a complaint, then please remove it. It does not contribute anything to the informational value of this page.Kendrakendrah
@Kendrakendrah Your comment doesn't provide any informational value either. You have doubled the amount of comments that don't provide any informational value. This site has been ruined by the people running it. Sure, this is a discussion for meta, but frankly my dear I don't give a damn.Dermatome
It answers my other question. Unlike the accepted answer says - this code is actually necessary when compiling placement new on non-Microsoft environments, like STM. I figured that out using trial and error method to force compiler to compile placement new on STM. To replicate the behavior - make a class, then try to overwrite class instance with placement new on non-MS C++ code. Compiler refuses to compile it unless this overload is added. With MSVC it does nothing. But it is run, debugger enters a breakpoint set on it.Elamite
F
17

The correct answer is you cannot replace operator placement new.

§18.4.​1.3 Placement forms
These functions are reserved, a C++ program may not define functions that displace the versions in the Standard C++ library.

The rationale: The only purpose of the allocation and deallocation operators is to allocate and deallocate memory, so when given memory nothing more should be done. (The standard specifically notes that these functions "Intentionally perform no other action.")

Fossiliferous answered 9/9, 2010 at 13:45 Comment(6)
Wow. Visual C++ 9 happily allows that.Glycogenesis
@sharptooth: What's your test program? Not surprising, it's illegal in the same way it's illegal to add things (in general) to the std namespace. The language itself is none the wiser, but the standard library forbids it.Fossiliferous
I replaced void* operator new[](size_t, void* where) by going into my compiler's header files. It worked fine. Actually, I didn't replace it -- I removed it, to make it unusable, because it is unusable.Botvinnik
@PaulDuBois: Huh? Bad idea to edit compiler files, now you get to build on one very special configuration only; for what gain?Fossiliferous
@Fossiliferous Actually, now I get to fail the build on one very special configuration only. The gain is that I am informed if anyone in my codebase uses placement array operator new. The problems with that feature are well-documented.Botvinnik
Not useful, You can still override class specific placement new operations.Dermatome
B
5

Technically, a placement operator new is any operator new that takes additional arguments besides the size of the memory needed.

So, new(std::nothrow) X uses a placement operator new and so does new(__FILE__, __LINE__) X.

The only reason for overriding the operator new(size_t, void*) could be to add tracing information, but I think the need for that will be pretty low.

Bridgetbridgetown answered 9/9, 2010 at 9:3 Comment(4)
One reason for implementing it might be to force the use of a particular memory allocator; this has come up for us when doing complex things on Windows where it was necessary to force the use of the allocator used by one particular DLL rather than another one. (Yes, different libraries were using different allocators. It all worked, as long as code matched new from one lib with delete from the same lib.)Policy
The first sentence is wrong, placement new has a specific meaning. And placement new cannot be overloaded or replaced.Fossiliferous
@GMan: You are right. There seems to be no specific name for operator new overloads that take additional parameters, although they are usually invoked using the placement syntax.Bridgetbridgetown
@GMan: new called with extra arguments is called "placement new", whether or not that extra data is an address where the object should be constructed. From the standard "The new-placement syntax is used to supply additional arguments to an allocation function." (section [expr.new]). The first two sentences of the answer are correct. The last is wrong though, replacing ::operator new(size_t, void*) is forbidden, so you can't add tracing.Canaliculus
A
4

One example is at Stroustrup's FAQ.

Autrey answered 9/9, 2010 at 8:52 Comment(2)
Honestly I don't get that example.Glycogenesis
@Glycogenesis Found a similar example with some additional explanation here (though there were some slight inaccuracies)Bringhurst
K
1

The most obvious override would be to copy this implementation.

Another sensible one would be to add some checks (for example, verifying that there is no "bound-marker" within the request zone).

I think however that the point is more than you HAVE to override it, as soon as you override the others (for a given class), because of the mechanics of name look up (or not overriding it to prevent its use, that's fine too, but it's a conscious decision).

Kail answered 9/9, 2010 at 9:36 Comment(0)
B
1

The most important extra-functionality for placement new overload would be to check address alignment.

For example, lets assume some class requires 16-byte alignment. Developer overloads new, new[], delete and delete[] - just to be sure everything is aligned properly.

Everything works fine to the moment when he tries to use his class with library which uses placement new... Library has no idea if/what alignment is required for the class and address it tries to "place" the object to might not be aligned - big boom.

The simplest example of such situation - try using std::vector<T> where T requires non-standard alignment.

Overload for placement new allows to detect if pointer is not aligned - might save hours of debugging.

Bancroft answered 3/10, 2014 at 6:46 Comment(0)
C
1

To define your own memory management for a prereserved area is one nice use.

To have different views on the same physical data (no need to move the data) is other interseting use. It also allows you reading a structured file as chars on a buffer and then, the superimposition of the their logical structure by defining an object of that the class over the buffer. The combination of this thing with the memory mapping of files, can provide big improvements in performance. The memory mapped hardware... So, thousand applications!

Confluence answered 4/3, 2015 at 7:29 Comment(1)
Could you please provide an example? This question is not about using placement new from user code, it's about overloading the operator.Glycogenesis
S
0

I've seen an example where two-argument new [] was overwritten to return memory blocks pre-filled with the char passed as the additional argument. I don't remember what the original code used (probably memset()), but it was functionally something like this:

#include <iostream>
#include <algorithm>
#include <new>
void* operator new [](size_t n, char c)
{
        char* p = new char[n];
        std::fill(p, p+n, c);
        return p;
}
int main()
{
        char* p = new('a') char[10];
        std::cout << p[0] << p[1] << ".." << p[9] << '\n';
}

although I guess this wouldn't be called "placement" new because it does not perform placement. It could probably be useful if templated so that it can build arrays of any type, filled with a copy of the object passed as its second argument... but then, we have containers for that anyway.

Safko answered 9/9, 2010 at 10:25 Comment(1)
It is called placement new, e.g. the standard says: "This overhead may be applied in all array new-expressions, including those referencing the library function operator new[](std::size_t, void*) and other placement allocation functions."Canaliculus
S
0

I'm not exactly sure of the question, but the following overrides placement new at the class level:

struct Bar {
void* operator new(size_t /* ignored */, void* where) throw() { return where; }
};

int main() {
  char mem[1];
  Bar* bar = new(mem) Bar;
}

I believe this is legal C++ (and compiles and runs fine with gcc 4.4.6).

You are free to change the implementation of this operator as you see fit (including removing the throw() clause, which will mean the compiler no longer checks the where pointer for null before calling the constructor). Tread carefully though.

§18.4.​1.3 is interesting. I believe this just applies to the global operator new function, not class specific ones.

Simmers answered 19/9, 2013 at 11:43 Comment(4)
The question was whether any other implementation was possible. What else could I possibly do except return where;?Glycogenesis
Ah, I see. Well, you could do some checking to make sure that this address isn't already used, doesn't overlap with already allocated memory, or you could even adjust where to be better aligned (returning where + n bytes). None of this I've ever seen before in practice.Simmers
It compiles, but are you sure your override is being called?Shelah
Yes I am sure (as I've had to use this in production code before). To verify this, put a throw into the function body, and then create a new instance of this type.Simmers
O
-1

My primary usage is to create a large array of objects. Its performing much better and has less overhead to allocate the memory in a whole block, i.e. using VirtualAlloc from Win32 (when programming windows). Then you just pass a ptr within that block to each objects placement new such as:

char *cp = new char[totalSize];

for(i = 0; i < count; i++, cp += ObjSize)        
{                                                        
    myClass *obj = new(cp) myClass;             
}
Olav answered 9/9, 2010 at 9:30 Comment(1)
IIUC, he is not asking for usage cases of the placement new operator itself, but for usage cases of overloading it.Graphics

© 2022 - 2024 — McMap. All rights reserved.