I may want to use "new" operator in cases of:
1) to manage myself what is the lifetime of an object :
Objects which created without new (on the stack) , are created the moment they are declared and their constructor is called. they are automatically destroyed when the function which created them are done . with "new" , objects are created the moment I used "new" + constructor and destroyed the moment I call "delete" (which calls the destructor first)
2) to manage myself the scope of the object:
(generally speaking) as long as "delete" wasn't called on a dynamic allocated object - anyone who keeps a pointer to the object can use it . this is not the case when allocating objects without new - you must think when will the object be destroyed and the pointer to it gets invalid (for example, return a pointer of local object of a function will cause an error , known as "Segmentation fault").
3) when an object contains or point to another object , but the inner/pointed object should not be created yet:
in other words - to have full control WHEN to create an object
for example, linked list / trees - I don't know when another nodes will be appended to the linked list , I want to keep the option to point another object .
for this purpose I keep a pointer to the next node and when I need to append a new node - I use new
interesting use of new operator comes when needing to parse some text to data structure , for example XML and JSON. we don't know what will the xml or json will look like, or what order they'll have inside them. we just start with some map-like object , keeping some pointers inside of it and appending them new elements while parsing (using new).
the point is that when we want create element dynamically (e.g. we don't know exactly how will the object looks like 100% on compilation time) we use new.
4) in a multi-threaded environment:
In order to make an object accessible from multiple threads , and to avoid stack-allocating problems (see 1 and 2) , we allocate an object with new .
this makes it accessible to many threads without worrying about the object being destroyed automatically.
5) in some design patterns :
like Single-Tone and Factory . google it.
6) in order to prevent multiple copies of heavy objects:
let's consider the following semi-pseudocode:
Code:
string getTextFromFile(string filePath){
someFileStreamer filereader(filePath);
return fileReader.readAll(); //readAll returns a string
}
void anotherFunction(){
string fileContent = getTextFromFile(..)
}
in this code , there are few copying action preformed
a) inside readTextFromFile - readAll result is copied to the return value.
b) the return value is again copied inside anotherFunction to fileContent.
all good , but what if the file actually weight 3 megabytes? such copy is very very heavy. we can save many copyes by allocating a new string , and return pointer rather than a copy :
Code:
string& getTextFromFile(string filePath){
someFileStreamer filereader(filePath);
return *new string(fileReader.readAll()); //readAll returns a string
}
void anotherFunction(){
string& fileContent = getTextFromFile(..)
}
now we reduced 2 excess copies to 1. (wher new string(..) is created);
interesting anecdote:
because c and c++ compiles entirely to assembly code, that gives us the privilege to allocated objects without "new" operator. that because that when a program compiles - it compiles directly to the operating system environment. that why C and C++ are called "Native" - they talk directly to the operating system in it's own language .
other managed languages , like Java and C# , are managed one. because the code basically is interpreted and not compiles to assembly - all the objects has to be allocated with "new" , since everything is happening at runtime.