13

In the following:

int main()
{
    new int; // Works
    
    
    int* pmem = 0;

    new (pmem) int;// Doesn't recognize new keyword/operator/function???

}

It won't recognise 'new' in this case without including the < iostream > header. Why is that? Why doesn't 'new' require a header but placement new does? If 'new' requires a function to be defined then why does 'int* a = new int;' work? Since it's not defined anywhere, I assumed it's part of the language. However 'new (&int) int;' 'placement new' isn't part of the language?

Visual Studio gives error:

'operator new': no overloaded function takes 3 arguments

Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • I wouldn't even rely on that. Placement new is provided by mandate when you include `` . That it "works" for you when you include `` is a symptom, not a cure. The regular forms of `operator new` that you are familiar with are [implicitly available](https://en.cppreference.com/w/cpp/memory/new/operator_new) by standard mandate – WhozCraig Aug 24 '21 at 06:49
  • 1
    Relevant [When is #include library required in C++?](https://stackoverflow.com/questions/2788388/when-is-include-new-library-required-in-c) – Quimby Aug 24 '21 at 06:52
  • That is not actually a duplicate. While relevant, it is asking (and answering) a different question. – Galik Aug 24 '21 at 07:00

1 Answers1

20

Placement new isn't just for "no-op" allocation. It's a general term for providing extra arguments to new beyond the object size. A standard example would be std::nothrow.

Since we are providing arguments, the compiler has to do overload resolution to choose an appropriate operator new function. And that means that overloads must be declared beforehand. The most basic overload is implicitly declared (in a way), while void* operator new(std::size_t, void* ptr) noexcept (the standard library function that does this "allocation") is not. So we must include the header (<new>*) for overload resolution.

That was the design choice made 30 years ago. It could have been done by another built-in, but since placing objects into pre-allcoated raw storage is deemed a pretty advanced feature (as opposed to simple dynamic allocation), adding a library dependency probably didn't seem like much of a hindrance.


* - You saw <iostream> affecting the behavior because it probably includes <new> either directly or indirectly. It's permissible, but not required behavior.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • I'm trying to get my head around this. new is mentioned as an operator, but it very much looks like an overloaded function call. I call new (pToMem) obj{ }; And it's as if the first argument of size_t is implicitly provided. Is it a function call whereas the the ordinary new is an operator? – Zebrafish Aug 24 '21 at 07:04
  • 3
    `new T` is an expression. Part of its evaluation involves calling a function (`operator new`). That's always true. The unintuitive bit is that one function is always implicitly declared. This is because simple dynamic allocation is pretty basic thing used in many programs. Other forms of the `new` expression require an explicit declaration. – StoryTeller - Unslander Monica Aug 24 '21 at 07:08
  • I can never a constructor myself, right? So if I want to construct an object at memory I want, say in my container, this is the only way I can do that, placement new, and I need to include the header, right? – Zebrafish Aug 24 '21 at 07:21
  • But why doesn't the compiler need to do overload resolution to call `void* operator new(std::size_t)` when you do `new int;`? – Joseph Sible-Reinstate Monica Aug 24 '21 at 18:04
  • @Joseph - Who says it doesn't? It may, or it may not do overload resolution. It may implicitly declare the function, or it may hard code a call to it sometimes. It works like that because the standard says so. Just like it's possible to "replace" those allocation functions (despite no other free functions supporting such a thing). It's simply how the behavior is defined. – StoryTeller - Unslander Monica Aug 24 '21 at 18:17