Imagine the following. You use C ++ 03 and you write:
string a("hello"); string b = a;
At this point, you have two lines of objects a and b , and each of them has its own buffer for storing an array of characters. Although the contents of the buffers are exactly the same, a and b still have their own copy of hello. This is a waste of memory. If they share a buffer, you will have to use a single char array to store "hello world" for both lines.
Now with QString this is a little different:
QString a("Hello"); QString b = a;
In this case, only a created a char array to store hello. b instead of creating its own char array, it just points to a char array. This way you save memory.
Now, if you execute b[0]='M' , id est, you modify b , then b creates its own char array, copying the contents of the array a , and then modifying its own array.
In Java, strings are immutable objects. In other words, Java does not provide any methods in the String class to modify its contents. This is done so that you can always transfer this kind of data.
In addition to things mentioned by others:
How to find out that I can free a char array?
To do this, use the "account". When an object is created and configured to point to a char array, its reference count will be incremented by 1, so it knows how many objects are still using it. When the object that points to it is destroyed, the reference count is reduced. When the counter reaches zero, the char array knows that no one is using it, so it can be freed.
This is a very crude implementation of reference counting. I do not intend to be exact or correct in any case. I ignore the correct ways to implement copy constructors and assignment operators in C ++. I cannot check if the implementation is working. Think of it as a description of an algorithm similar to C ++. I just want to teach concepts. But imagine that you have these classes:
class SharedData{ private: int refcount; int data; public: SharedData(int _data){data=_data;refcount=1;} void incRef(){refcount++;} void decRef(){--refcount; if(refCount==0) delete this;} }; class Data{ SharedData* shared; public: Data(int i){shared = new Data(i);} Data(const Data& data){shared = data.shared; shared->incRef();} const Data& operator=(const Data& data){if(shared!=data.shared){ shared->decRef(); shared = data.shared; shared->incRef();} } ~Data(){shared->decRef();} };
Two objects of the Data class can share the same SharedData object, therefore:
void someFunction() { Data a(3) //Creates a SharedData instance and set refcount to 1 if (expression) { Data b = a; //b points to the same SharedData than a. refcount is 2 b = Data(4);// b points to diferent SharedData. refcount of SharedData of a is decremented to 1 and b SharedData has refcount 1 //destructor of b is called. Because shared data of b has now refcount == 0, the sharedData is freed; } //destructor of a is called, refcount is decremented again // because it is zero SharedData is freed }
In this way, resource utilization was maximized and the copy was minimized. Both a and b used the same SharedData (aka int 3 )., 4 not copied from a to b , they just shared the same data. Int doesn't really matter, but imagine if SharedData contained some sort of large string or any other more complex data structure. Copying just a pointer is much faster than dozens of bytes. And it also saves a lot of memory when you really don't need a copy.
What is copy-on-write?
Recall above what I said when we did b[0]='M' . It was copying to record. b and a used the same char array. But b needs to change the line. He could not do this directly, because that would also change the line for a . Therefore, b must create its own copy of the char array in order to be able to modify it. Since it should only create a copy when it changes the array, it is called copy-on-write.