Operator New/Delete

 

Operator New/Delete

In the first newsletter we talked about using C++ as a better C. This term doesn't have a precise meaning, but one way of looking at it is to focus on the features C++ adds to C, exclusive of the most obvious one, namely the class concept used in object-oriented programming.

One of these features is operator new and operator delete. These are intended to replace malloc() and free() in the C standard library. To give an example of how these are similar and how they differ, suppose that we want to allocate a 100-long vector of integers for some purpose. In C, we would say:

        int* ip;

        ip = (int*)malloc(sizeof(int) * 100);

        ...

        free((void*)ip);

With new/delete in C++, we would have:

        int* ip;

        ip = new int[100];

        ...

        delete ip;

The most obvious difference is that the C++ approach takes care of the low-level details necessary to determine how many bytes to allocate. With the C++ new operator, you simply describe the type of the desired storage, in this example "int[100]".

The C and C++ approaches have several similarities:

        - neither malloc() nor new initialize the space to zeros

        - both malloc() and new return a pointer that is suitably
        aligned for a given machine architecture

        - both free() and delete do nothing with a NULL pointer

malloc() returns NULL if the space cannot be obtained. Many versions of new in existing C++ compilers do likewise. However, the draft ANSI C++ standard says that a failure to obtain storage should result in an exception being thrown or should result in the currently installed new handler being invoked. In these newsletters we are assuming that NULL is returned.

The idea of a new handler can be illustrated as follows:

        extern "C" int printf(const char*, ...);
        extern "C" void exit(int);

        typedef void (*new_handler)(void);

        new_handler set_new_handler(new_handler);

        void f()
        {
                printf("new handler invoked due to new failure/n");
                exit(1);
        }

        main()
        {
                float* p;

                set_new_handler(f);

                for (;;)
                        p = new float[5000];    // something that will
                                                // fail eventually
                return 0;
        }

A new handler is a way of establishing a hook from the C++ standard library to a user program. set_new_handler() is a library function that records a pointer to another function that is to be called in the event of a new failure.

It is possible to define your own new and delete functions. For example:

        void* operator new(size_t s)
        {
                // allocate and align storage of size s

                // handle failure via new_handler or exception

                // return pointer to storage
        }

        void operator delete(void* p)
        {
                // handle case where p is NULL

                // handle deallocation of p block in some way
        }

size_t is a typedef, typically defined to mean "unsigned int". It's found in a header file that may vary between compiler implementations.

(clarification of above)

In the previous issue of the newsletter, there was an example:

        int* ip;

        ip = new int[100];

        delete ip;

This code will work with many compilers, but it should instead read:

        int* ip;

        ip = new int[100];

        delete [] ip;

This is an area of C++ that has changed several times in recent years. There are a number of issues to note. The first is that new and delete in C++ have more than one function. The new operator allocates storage, just like malloc() in C, but it is also responsible for calling the constructor for any class object that is being allocated. For example, if we have a String class, saying:

        String* p = new String("xxx");

will allocate space for a String object, and then call the constructor to initialize the String object to the value "xxx". In a similar way, the delete operator arranges for the destructor to be called for an object, and then the space is deallocated in a manner similar to the C function free().

If we have an array of class objects, as in:

        String* p = new String[100];

then a constructor must be called for each array slot, since each is a class object. Typically this processing is handled by a C++ internal library function that iterates over the array.

In a similar way, deallocation of an array of class objects can be done by saying:

        delete [] p;

It used to be that you had to say:

        delete [100] p;

but this feature is obsolete. The size of the array is recovered by the library function that implements the delete operator for arrays. The pointer/size pair can be stored in an auxiliary data structure or the size can be stored in the allocated block before the first actual byte of data.

What makes this a bit tricky is that all of this work of calling constructors and destructors doesn't matter for fundamental data types like int:

        int* ip;

        ip = new int[100];

        delete ip;

This code will work in many cases, because there are no destructors to call, and deleting a block of storage works pretty much the same whether it's treated as an array of ints or a single large chunk of bytes.

But more recently, the ANSI standardization committee has decided to break out the new and delete operators for arrays as separate functions, so that a program can control the allocation of arrays separately from other types. For example, you can say:

        void* operator new(unsigned int) {/* ... */ return 0;}

        void* operator new[](unsigned int) {/* ... */ return 0;}

        void f()
        {
                int* ip;

                ip = new int;           // calls operator new()

                ip = new int[100];      // calls operator new[]()
        }

and the appropriate functions will be called in each case. This is kind of like defining your own versions of the malloc() and free() library functions in C.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值