You can do the same kind of initialization in your DSString& copy constructor that you do in your char* converting constructor, simply use the data member of the input DSString as the char* to copy from, eg:
DSString::DSString(const char *d) { // the behavior of strlen() and strcpy() are undefined if d is null... if (d) { data = new char[strlen(d) + 1]; strcpy(data, d); } else data = nullptr; } DSString::DSString(const DSString &src) { // the behavior of strlen() and strcpy() are undefined if src.data is null... if (src.data) { data = new char[strlen(src.data) + 1]; strcpy(data, src.data); } else data = nullptr; }
Or, since you are clearly using C++11 or later (by virtue of the use of nullptr), you can simply have your copy constructor delegate to your converting constructor itself to avoid repeating code:
DSString::DSString(const DSString &src) : DSString(src.data) { }
Don't forget to also include a destructor, a move constructor, a copy assignment operator, and a move assignment operator, per the Rule of 3/5/0:
DSString::DSString(DSString &&src) : DSString() { //std::swap(data, src.data); data = src.data; src.data = nullptr; } DSString::~DSString() { delete[] data; } DSString& DSString::operator=(const DSString &rhs) { if (&rhs != this) { DSString tmp(rhs); //std::swap(data, tmp.data); char *d = data; data = tmp.data; tmp.data = d; } return *this; } DSString& DSString::operator=(DSString &&rhs) { DSString tmp(std::move(rhs)); //std::swap(data, tmp.data); char *d = data; data = tmp.data; tmp.data = d; return *this; }
Now, that being said, if you were to use std::string instead of char* for your data member (as you should), you get most of this functionality for free from the compiler, you don't have to implement it manually, except for the char* converting constructor:
class DSString { private: std::string data; public: DSString() = default; DSString(const char *d) : data(d ? d : "") {} DSString(const DSString&) = default; DSString(DSString&&) = default; ~DSString() = default; DSString& operator=(const DSString&) = default; DSString& operator=(DSString&&) = default; };
std::stringinstead?std::stringis less advanced (simpler and safer to use) thannewanddelete.