Why is ::operator new[] necessary when ::operator new is enough?

后端 未结 5 958
谎友^
谎友^ 2020-12-24 13:18

As we know, the C++ standard defines two forms of global allocation functions:

void* operator new(size_t);
void* operator new[](size_t);

An

相关标签:
5条回答
  • 2020-12-24 13:30

    I'm sure there are proper use-cases out there that require separate new[] and new, but I haven't encountered one yet that is uniquely possible with this separation and nothing else.

    However, I see it like this: since the user calls different versions of operator new, the C++ standard would have been guilty of wantonly and deliberately losing information if they'd defined just one operator new and had both new and new[] forward there. There is (literally) one bit of information here, that might be useful to somebody, and I don't think people on the committee could have thrown it out in good conscience!

    Besides, having to implement the extra new[] is a very very minor inconvenience to the rest of us, if at all, so the trade off of preserving a single bit of information wins against having to implement a single simple function in a small fraction of our programs.

    0 讨论(0)
  • 2020-12-24 13:43

    The standard (n3936) makes it clear that these two operators serve different but related purposes.

    operator new calls the function void* operator new(std::size_t). The first argument must be identical to the argument to the operator. It returns a block of storage suitably aligned, and which may be somewhat larger than required.

    operator new[] calls the function void* operator new[](std::size_t). The first argument may be larger than the argument supplied to the operator, to provide extra storage space if required for array indexing. The default implement for both is to simply call malloc().

    The purpose of operator new[] is to support specialised array indexing, if available. It has nothing to do with memory pools or anything else. In a conforming implementation that made use of this feature, the implementation would set up specialised tables in the extra space and the compiler would generate code for instructions or calls to library library support routines that made use of those tables. C++ code using arrays and failing to use new[] would fail on those platforms.

    I am not personally aware of any such implementation, but it resembles the kind of features required for the support of certain mainframes (CDC, IBM, etc) which have an architecture quite unlike the Intel or RISC chips we know and love.

    In my opinion, the accepted answer is incorrect.


    Just for completeness, the standard (n3936 mostly in S5.3.4) contains the following.

    1. A distinction between allocating an 'array object' or a 'non-array object'
    2. References to 'array allocation overhead', with the implication that extra storage might be needed and it might (somehow) be used for a repetition count or element size.

    There is no reference to memory pools or any hint that this might be a consideration.

    0 讨论(0)
  • 2020-12-24 13:45

    I think ::operator new[] may have been useful for fairly specialized systems where "big but few" arrays might be allocated by a different allocator than "small but numerous" objects. However, it's currently something of a relic.

    operator new can reasonably expect that an object will be constructed at the exact address returned, but operator new[] cannot. The first bytes of the allocation block might be used for a size "cookie", the array might be sparsely initialized, etc. The distinction becomes more meaningful for member operator new, which may be specialized for its particular class.

    In any case, ::operator new[] cannot be very essential, because std::vector (via std::allocator), which is currently the most popular way to obtain dynamic arrays, ignores it.

    In modern C++, custom allocators are generally a better choice than customized operator new. Actually, new expressions should be avoided entirely in favor of container (or smart-pointer, etc) classes, which provide more exception safety.

    0 讨论(0)
  • 2020-12-24 13:46

    The C++ Programming Language: Special Edition p 423 says

    _The operator new() and operator delete() functions allow a user to take over allocation and deallocation of individual objects; operator new[]() and operator delete[]() serve exactly the same role for the allocation and deallocation of arrays.

    Thanks Tony D for correcting my misunderstanding of this nuance.

    Wow, it's not often I'm caught out on something in C++ I'm so certain about - I must have been spending too much time in Objective-C!

    original wrong answer

    It's simple - the new[] form invokes the constructor on every element of a classic C array.

    So it first allocates the space for all the objects, then iterates calling the constructor for each slot.

    0 讨论(0)
  • 2020-12-24 13:48

    ::operator new[] and ~delete[] facilitate memory usage debugging, being a central point to audit allocation and deallocation operations; you can then ensure the array form is used for both or neither.

    There are also lots of plausible if highly unusual/crude tuning uses:

    • allocate arrays from a separate pool, perhaps because that crucially improved average cache hits for small single-object dynamically-allocated objects,

    • different memory access hints (ala madvise) for array/non-array data

    All that's a bit weird and outside the day-to-day concerns of 99.999% of programmers, but why prevent it being possible?

    0 讨论(0)
提交回复
热议问题