How to Call the Original "Operator New" If I Have Overloaded It

How do I call the original operator new if I have overloaded it?

You can't access them because it isn't really overloading, it's replacement. When you define your own ::operator new, the old one goes away. That's pretty much that.

Essentially, you need to call malloc from a custom ::operator new. Not only that, but also follow the directions in 18.4.1.1/4 to properly handle errors:

Default behavior:

— Executes a loop:
Within the loop, the function first
attempts to allocate the requested
storage. Whether the attempt involves
a call to the Standard C library
function malloc is unspecified.


Returns a pointer to the allocated
storage if the attempt is successful.
Otherwise, if the last argument to
set_new_handler() was a null pointer,
throw bad_alloc.

— Otherwise, the
function calls the current new_handler
(18.4.2.2). If the called function
returns, the loop repeats.

— The loop
terminates when an attempt to allocate
the requested storage is successful or
when a called new_handler function
does not return.

Overloading operator new for other class

My thanks to François Andrieux for his timely answers. The short answer to my question is to create a factory pattern to create Message objects. Something like :

(Node.cpp)

unique_ptr<Message> Node::createMessage(size_t capacity) {
return unique_ptr(new Message(capacity + header_size));
}

That way, the user doesn't have to precise the header size every time they want to create a new message object. The downside of this is that the user has to know the exact method to use. Forcing the user to use this method is possible if the Message natural constructor is made inaccessible.

Overloading the operator new is not the answer, and the justification is the following :

There are only two options for overloading operator new. You can overload the global operator new or the member operator new. The global operator new will impact all uses of new in the current translation unit, so we can ignore that one. It won't be useful here. The other option is overloading operator new for a specific class as a member operator. However, that only changes how allocating that class is done. If you overload Node::operator new then you only change what happens when you do new Node. You can't change Message::operator new from within Node

Another possibility to allocate more space than the natural constructor would do is to use placement new. However this makes construction and destruction over-complicated which is not the intended objective here. Also, it would be less risky to let the user write new Message(header_size + capacity) every time than let him allocate and free memory.

C++: If I overload new operator, do I have to overload the delete operator too?

What this means is that if you overload operator new with extra arguments, and not the corresponding delete with extra arguments, if an exception occurs in a constructor, no delete operator will be called. On the other hand, if you're overloading the basic new (with no extra arguments), and an exception occurs, delete with no extra argument will be called, and that will be the default operator delete if you have not overloaded it.

when overloading new operator it doesnt allocate memory for char pointer

From operator new, operator new[]

Class-specific overloads

Both single-object and array allocation functions may be defined as public static member functions of a class (versions (15-18)). If defined, these allocation functions are called by new-expressions to allocate memory for single objects and arrays of this class,

  • So the new operator allocates memory for new instances of the class, not for the attributes of the class.
  • If you need to allocate memory for attributes of the class do that e.g. in the constructor.
  • Avoid the use of char* for strings. Rather use C++ Strings.
  • Avoid pointers as much as possible. Have a look at smart pointers.

For the sake of completeness, if you must use char*, you can use strlen, new, strncpy and delete to do this. Do not use strcpy as this can cause an overflow.. (To get the below to compile in VS2015 you will need to add the _CRT_SECURE_NO_WARNINGS to the preprocessor definitions.)

int length = strlen(source) + 1;
char *destination = new char[length];
if (destination) {
strncpy(destination, source,length);
}
...
delete destination //do not forget to free the allocate memory

Here is the Student class.

  • The 1st constructor takes a char* (for demonstration purposes only!)
  • But better, the 2nd constructor uses

    • no pointers,
    • it uses C++ strings, and
    • uses the constructors initializer list to setup the attributes.
  • new operator (just delegates to the global new operator).
  • delete operator (for completeness, delegates to global delete operator).

.

#include <iostream>
#include <string>

// class-specific allocation functions
class Student {

char *nameCharArray; //this only for demonstration
std::string name; //prefer string
int age;
public:
Student(char *name, int age) : age(age)
{
int length = strlen(name) + 1;
nameCharArray = new char[length];
if (this->nameCharArray) {
strncpy(this->nameCharArray, name, length);
}
this->name = std::string(nameCharArray);
}

Student(std::string &name, int age) : name(name), age(age) {}

~Student() {
std::cout << "Freeing name... " << std::endl;
delete nameCharArray;
}

std::string getName() const {
return name;
}

static void* operator new(std::size_t sz)
{
std::cout << "custom new for size " << sz << '\n';
return ::operator new(sz);
}

static void operator delete(void* ptr, std::size_t sz)
{
std::cout << "custom delete for size " << sz << '\n';
::operator delete(ptr);
}

};

This is how the code is used

int main() {
char name[] = "studentname";
Student* p1 = new Student(name, 12);

std::cout << p1->getName() << std::endl;

delete p1;
}

why overloaded new operator is calling constructor even I am using malloc inside overloading function?

A new expression results in two separate things happening: allocation of the memory needed by the object begin created, and initialization of the object.

The new operator, on the other hand, just handles the allocation part. When you overload the new operator with respect to a specific class, you are replacing the allocation of memory to the object.

This division of functions makes sense when you realize that not all objects are allocated on the heap. Consider the following case:

int main() {
string someString;
..
}

The local variable is not dynamically allocated; new is not used; however the object still needs to be initialized so the constructor is still called. Note that you did not need to explicitly call the constructor - it is implicit in the language that an appropriate constructor will always be called to initialize an object when it is created.

When you write a 'new expression', the compiler knows to emit instructions to invoke the new operator (to allocate memory as needed) and then to call the constructor (to initialize the object). This happens whether or not you overload the new operator.



Related Topics



Leave a reply



Submit