What does the C++ new operator do other than allocation and a ctor call?

前端 未结 3 1111
傲寒
傲寒 2020-12-06 02:30

What are all the other things the new operator does other than allocating memory and calling a constructor?

3条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-06 03:18

    I've written a explanation of what it does in this answer. It explains how

    • new gets the memory
    • new handles memory failure
    • new handles constructor exceptions
    • new handles special placement and nothrow versions

    Michael explained how the default allocator function (::operator new) gets memory nicely and how it handles failure. I've seen your question on where the size of an object is stored in his comments. The answer is, there isn't size stored if not necassary. Remember that C doesn't need the size for free (and ::operator new can just use malloc):

    void * memory = malloc(x);
    free (memory); // no need to tell it the size
    

    Here is an example where you see how storing the size has an impact on the size of allocation for the array form of a new expression (not covered by my other answer):

    #include 
    #include 
    
    struct f {
        // requests allocation of t bytes
        void * operator new[](std::size_t t) throw() {
            void *p = ::operator new[](t);
            std::cout << "new    p: " << p << std::endl;
            std::cout << "new size: " << t << std::endl;
            return p;
        }
    
        // requests deleting of t bytes starting at p
        void operator delete[](void *p, std::size_t t) throw() {
            std::cout << "delete p: " << p << std::endl;
            std::cout << "size    : " << t << std::endl;
            return ::operator delete[](p);
        }
    };
    
    int main() {
        std::cout << "sizeof f: " << sizeof (f) << std::endl;
    
        f * f_ = new f[1];
        std::cout << "&f_     : " << f_ << std::endl;
        delete[] f_;
    }
    

    It will print out something like this:

    sizeof f: 1
    new    p: 0x93fe008
    new size: 5
    &f_     : 0x93fe00c
    delete p: 0x93fe008
    size    : 5
    

    One byte for the object itself and 4 bytes for the count which is stored just before the allocated area of the object. Now if we use the deallocation function without a size parameter (just removing it from the operator delete), we get this output:

    sizeof f: 1
    new    p: 0x9451008
    new size: 1
    &f_     : 0x9451008
    delete p: 0x9451008
    

    The C++ runtime here doesn't care about the size, so it doesn't store it anymore. Note that this is highly implementation specific, and that's what gcc does here to be able to tell you the size in the member operator delete. Other implementations may still store the size, and will most likely if there is a destructor to invoke for the class. For example just adding ~f() { } above makes gcc to store the size, regardless on what deallocation function we write.

提交回复
热议问题