-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add placement new operator #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Casting to void is a well known trick for prevening 'unused parameter' warnings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
/cc @matthijskooijman
Commit looks good to me. I believe there a few more things we could do to make support for new/delete more complete:
|
I don't have a copy of the standard to check with. I found an SO answer that claims §18.6 [support.dynamic] states that the new operator should be Originally I didn't think cppreference mentioned it in their listing of the contents of the
That looks to be functionally similar so it should be trivial to add. I'd be happy to add both the
You seem to have truncated the standard quote or at least are missing part of it. I could add a comment discussing the operator and its absense, but as I don't have a copy of the standard to hand I'd need to know what exactly the standard says about its use to be sure that its absense is unimportant and to know the best way to explain its absence. |
I actually don't have the final spec at hand, but was quoting from a draft standard that is publically available. A quick search shows an even newer version here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf |
Ah, the relevant quote is:
As per §18.6.1.3.9, or I believe this means that technically the default definition of placement new can't trigger this either. The definition is given as We could implement both versions (array and non-array) with a comment above each stating "this function is expected to be unused" and a comment in the bodies stating "this function intentionally does nothing". If it was left unimplemented, I'm not sure there's a particularly brief way to exaplain why it's unimplemented without leaving out information. I am happy with either approach. |
My interpretation was that it would be called when the class' constructor would throw an exception, since that's what initialization means AFAIU (calling the placement new operator is allocation rather than initialization). I can't find hard evidence of this, but it makes sense that a call to placement new is coupled to a call to placement delete, and if placement new fails (e.g. throws), there is no need to do placement delete. This seems consistent with sections like 5.3.4.23 (which says the return value of placement new is passed to placement delete, in addition to the "placement arguments", e.g.
I suspect this means the default intentionally performs no action, but if the default placement new provided by the compiler has any side effects, the placement delete allows undoing them. For reference, here's what gcc does: https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/new#L125 (see the new*.cpp files in the same directory for implementations). I see a few additional signatures there, like an aligned version (not in the spec AFAICS), but also a delete that takes a size argument and nothrow versions of everything, which are in the spec. I guess there is no additional value in those (the nothrow version could be useful for making sketches more portable with platforms that do use exceptions, but that would also require defining bits of the Given the extra versions, we'll either have to implement a ton more, or end up not implmenting everything anyway. Hence, I'd suggest we just leave the code as is, but add a comment:
It is not really consise, but does capture what we learned for future reference, I guess? |
Sorry for the delay in replying to this, I have been preoccupied with other projects.
I think calling the placement new operator is initialisation, as the pointer passed to placement new should point to a block of bytes that have already been allocated (be it statically or dynamically). Regardless of terminology, I've looked around and several places (e.g. Wikipedia, Stack Overflow) indicate placement delete is intended to be called when the constructor of an object in a placement new expression throws an exception. I.e. In
I think you're looking for
If you mean But I think for now the scope of this PR should be limited to just the 4 placement operators specified by "Placement forms", §18.6.1.3 of C++14 (of which N4296 is a draft), and to ignore any other overloads for now, such as I think it's better to keep the scope of this PR small, and to assess the usefulness of the other operators another day in another PR. So that leaves us with four operators:
I shall add What does everyone else think? Out of interest, I checked a C++17 draft, N4713 and found that the "Placement forms" section had been relocated to §21.6.2.3 and renamed "Non-allocating forms", but that the same 4 operators were defined, with just one amendment - the addition of a |
Sounds ok to me.
As mentioned, I do not see direct value in the placement delete forms, but they should not harm either (and for consistency, implementing them is probably a good idea). A comment might still be useful for the other new operators, but I'm not really attached to that comment. |
The standard mandates that placement new should be have a noexcept specifier.
This adds the missing placement new operator.
The placement new operator is especially useful when working with raw data buffers (often used when implementing data structures to avoid requiring a default constructor).
More information about placement new can be found here:
https://en.cppreference.com/w/cpp/language/new#Placement_new