Your String
class cannot be used to build a program upon, due to the faults within the String
class. You must fix those errors first before even thinking about using String
as a string class.
Therefore this answer addresses how to fix String
first -- from there, you should now be able to write the program knowing you're not working on a faulty foundation.
Error 1: Default construction
You failed to initialize sptr
when a String
is default constructed. Thus when ~String()
is executed, the call to delete
will attempt to delete
an uninitialized pointer.
Simple 1 line main
functions such as this one:
int main()
{
String s;
} // <-- destructor of s may crash
will show undefined behavior and may crash, as shown by this example.
To fix this:
class String
{
public:
String() : sptr(nullptr) {}
//...
};
Now when delete []
is issued on sptr
, no harm will occur since it is perfectly valid to delete []
a nullptr
(it becomes basically a no-op).
Error 2: Faulty assignment operator
Your String::operator=
fails to deallocate the previous memory that was allocated. In addition, the check for NULL
is incorrect, since &other
will always be true
.
I am assuming this is the check for self-assignment, but it is not written correctly. The check for self-assignment is done by comparing the address of the current object (this
) with the address of the object being passed in:
if (this != &other)
Once you have that, then you could have written the rest of the function this way:
if(this != &other)
{
String tmp( other );
std::swap(tmp.sptr, sptr);
}
return *this;
All this function does is copy other
to a temporary String
called tmp
, swap out the sptr
with the tmp.sptr
and let tmp
die off with the old data. This is called the copy / swap idiom, where you're just swapping out the contents of the current object with the contents of the temporary object, and letting the temporary object die off with the old contents.
Note that the check for self-assignment isn't necessary when using copy / swap, but there is no harm done in making the check (could even be a small optimization done when the check for self-assignment is present).
Edit: The other issue is that operator=
should return a reference to the current object, not a brand new String
object. The signature should be:
String& operator=( const String& other ) // <-- note the return type is String&
{
//... code
//...
return *this;
}
Error 3: Wrong form of delete
Since you allocated using new []
, you should be using delete []
, not just delete
in the destructor:
~String()
{
delete [] sptr;
}
Given all of these changes, the following code no longer has issues, as shown by the Live Example here.
Now that you have a working String
class, then you can build your application from there.
As to your program, you can easily change your string by using the assignment operator. There is no need for a change()
function:
String a2("Hello ");
a2.display();
a2 = "Java ";
a2.display();
Since String::operator=(const String&)
is no longer faulty with the changes above, assignment can now be done without issues.