I am a C++ beginner. And I am doing the exercises in C++ Primer (5th Edition). I found a reference to Exercise 13.8 from Github (Here), which is shown below.
#include <string>
#include <iostream>
using std::cout;
using std::endl;
class HasPtr {
public:
HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }
HasPtr(const HasPtr &hp) : ps(new std::string(*hp.ps)), i(hp.i) { }
HasPtr& operator=(const HasPtr &hp) {
std::string *new_ps = new std::string(*hp.ps);
delete ps; // I don't know why it is needed here?
// But when I delete this line, it also works.
ps = new_ps;
i = hp.i;
return *this;
}
void print() {
cout << *(this->ps) << endl;
cout << this->i << endl;
}
private:
std::string *ps;
int i;
};
int main() {
HasPtr hp1("hello"), hp2("world");
hp1.print();
hp1 = hp2;
cout << "After the assignment:" << endl;
hp1.print();
}
What makes me confusing is the HasPtr& operator=(const HasPtr &hp)
function. I don't know why delete ps;
is needed here. I thought it was an error, but it worked when I compiled the code. However, it also works when I delete the line of delete ps;
. So, I do not know whether delete ps;
is needed and what is the advantage if it is reserved.
HasPtr::ps
is an heap-allocated std::string
pointer.
It is allocated and constructed using new
in all HasPtr
constructors. Therefore, when HasPtr::ps
gets replaced by another heap-allocated pointer, the existing memory has to be released using delete
to avoid memory leaks.
Note that, in modern C++, you should almost never use new
and delete
for managing objects like this. Use smart pointers instead, like std::unique_ptr
or std::shared_ptr
, which take care of memory management for you, safely and conveniently.
I still suggest getting familiar with new
and delete
, as an huge amount of existing code makes use of them. cppreference.com
is a great place to find detailed information about the language.
As Jan Hudec mentioned in the comments, it is generally pretty silly to store an std::string
on the heap - std::string
is a wrapper around an heap-allocated character array, which already manages the memory for you.
It's needed to prevent a memory leak: every new
must be balanced with a delete
.
You allocate memory for ps
with a new
in the constructors.
When you allocate memory for new_ps
and assign this to ps
, you need to free the constructor-allocated memory before you lose the old pointer value.
You program will indeed "work" if you omit that line, but it will steadily consume more and more memory, until, eventually there is no more memory left.
Note that you have another memory leak: you need to create a destructor, and call delete ps
in it.
As you can see, this is getting unduly complicated. Better still, ditch all this pointer stuff and use a std::string s
as the member variable - it takes care of all the memory management for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With