1
\$\begingroup\$

I want to practise global operator new/delete and new[]/delete[], how can I improve it? Here are one Fruit(Base) Class, and one Apple(Derived) Class.

/*************Fruit.h*****************/    
#ifndef _FRUIT_H
#define _FRUIT_H
#include <cstdlib>
#include <iostream>
#include <exception>

/***************************************GLOBAL operator new/delete/[]***************************/

void * operator new(decltype(sizeof(0)) n) noexcept(false) 
{
    void *vp = malloc(n);
    if (vp == nullptr)
    {
        throw std::bad_alloc();
    }
    std::cout <<  "Global---::new " << std::hex << n << ")  " << vp << std::endl;
    return vp;
}
void* operator new[](decltype(sizeof(0)) n) noexcept(false)
{
    void *vp = malloc(n);
    if (vp == nullptr)
    {
        throw std::bad_alloc();
    }
    std::cout <<  "Global---::new[] " << std::hex << n << ")  " << vp << std::endl;
    return vp;
}
void operator delete (void *ptr) noexcept 
{
    std::cout << "Global---::delete(" << std::hex << ptr << ")" << std::endl;
    free(ptr);  // nullptr-safe
}

void operator delete[](void *ptr) noexcept
{
    std::cout  << "Global---::delete[] " << std::hex << ptr << ")" << std::endl;
    free(ptr);  // nullptr-safe
}
virtual ~Fruit() {}

/***********************************************Fruit*******************************************************/

class Fruit {
public:
    static void* operator new (decltype(sizeof(0)) n) noexcept(false)
    {
        void *vp = ::operator new (n);    // might throw std::bad_alloc
        std::cout << std::hex << "Fruit::new(" << n << ") " << vp << std::endl;
        return vp;
    }
    static void* operator new[](decltype(sizeof(0)) n) noexcept(false)
    {
        void *vp = ::operator new (n);    // might throw std::bad_alloc
        std::cout << std::hex << "Fruit::new[](" << n << ") " << vp << std::endl;
        return vp;
    }
        static void operator delete (void *vp) noexcept
    {
        std::cout << "Fruit::delete(" << std::hex << vp << ")" << std::endl;
        ::operator delete (vp);
    }
    static void operator delete[](void *vp) noexcept
    {
        std::cout << "Fruit::delete[](" << std::hex << vp << ")" << std::endl;
        ::operator delete[](vp);
    }
private:
    int no;
    double weight;
    char key;
public:
    Fruit() = default;
    constexpr Fruit(int no, double weight, char key) : no(no), weight(weight), key(key) {}
    void print() {   }
    virtual void process() {   }
};

/****************************************Apple**********************************************/
class Apple : public Fruit {
public:
    static void* operator new (decltype(sizeof(0)) n) noexcept(false)
    {
        void *vp = ::operator new (n);    // might throw std::bad_alloc
        std::cout << std::hex << "Apple::new(" << n << ") " << vp << std::endl;
        return vp;
    }
    static void* operator new[](decltype(sizeof(0)) n) noexcept(false)
    {
        void *vp = ::operator new (n);    // might throw std::bad_alloc
        std::cout << std::hex << "Apple::new[](" << n << ") " << vp << std::endl;
        return vp;
    }
        static void operator delete (void *vp) noexcept
    {
        std::cout << "Apple::delete(" << std::hex << vp << ")" << std::endl;
        ::operator delete (vp);
    }
    static void operator delete[](void *vp) noexcept
    {
        std::cout << "Apple::delete[](" << std::hex << vp << ")" << std::endl;
        ::operator delete[](vp);
    }
private:
    int size;
    char type;
public:
    Apple() = default;
    constexpr Apple(int no, double weight, char key, int size, char type) : Fruit(no, weight, key), size(size), type(type) {}
    void save() {   }
    virtual void process() {   }
};
#endif // !_FRUIT_H

/***************main.cpp*************/
#include "stdafx.h"
#include "Fruit.h"
int main()
{
    Fruit *fruit = new Fruit; //default constructor
    delete fruit;
    std::cout << "\n";
    Fruit *fruits = new Fruit[5];
    delete[] fruits;
    std::cout << "\n";
    Apple *apple = new Apple;
    delete apple;
    std::cout << "\n";
    Apple *apples = new Apple[5];
    delete[] apples;
    std::cout << "\n";
}

sample output:

Global---::new 20)  000001E872C9B470
Fruit::new(20) 000001E872C9B470
Fruit::delete(000001E872C9B470)
Global---::delete(000001E872C9B470)

Global---::new a0)  000001E872C97A40
Fruit::new[](a0) 000001E872C97A40
Fruit::delete[](000001E872C97A40)
Global---::delete[] 000001E872C97A40)

Global---::new 28)  000001E872C95550
Apple::new(28) 000001E872C95550
Apple::delete(000001E872C95550)
Global---::delete(000001E872C95550)

Global---::new c8)  000001E872C9C6A0
Apple::new[](c8) 000001E872C9C6A0
Apple::delete[](000001E872C9C6A0)
Global---::delete[] 000001E872C9C6A0)
\$\endgroup\$
  • \$\begingroup\$ Why are you doing this? decltype(sizeof(0)) \$\endgroup\$ – Martin York Nov 20 '17 at 5:50
  • 1
    \$\begingroup\$ @If un-include <cstdio>, I have to include the library like <cstddef>, which will make my head file too heavy. decltype(size(0)) can help me deduce std::size_t without extra head file. \$\endgroup\$ – 陳 力 Nov 20 '17 at 6:16
  • \$\begingroup\$ Too heavy? :-) ! \$\endgroup\$ – Martin York Nov 20 '17 at 6:37
  • \$\begingroup\$ @czxyl, the point you made doesn’t make any sense. Pre-C++17 it doesn’t even have type declarations. It has type aliases in std and around 3-4 macros. I bet that cstdio have included it anyway. Pretty much anything users will include will have cstddef. \$\endgroup\$ – Incomputable Nov 20 '17 at 6:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.