i write simple string class in cpp, when add new features bad happened. stack overflow when call object s3 destructor. spent hour fix it, did not find wrong code locially , grammer correct. ask friend recode me fix it, when recoded on mac. there no bad thing happened in program. really confused , need fix it, if there wrong codes in truth. if not, maybe should comment on issue visual studio 2015. :(
this mystlstring.h
class mystlstring { public: // default constructor mystlstring(); // constructs string count copies of character ch. mystlstring(size_t count, char ch); // convert char consequence mystlstring mystlstring(const char *s); // copy constructor mystlstring(const mystlstring &s); // destructor ~mystlstring(); using size_type = size_t; using chart = char; // character type using value_type = char; // value_type using reference = value_type; // reference using const_reference = const value_type&; // const reference // returns reference character @ specified location pos. reference at(size_type pos); // const_reference at(size_type pos) const; // not know how convert reference const_reference when return // returns reference first character chart& front(); const chart& front() const; // returns reference last character, equivalent operator[](size() - 1) chart& back(); const chart& back() const; // returns pointer underlying array serving character storage. chart* data(); const chart* data() const; // operator assignment overloaded mystlstring& operator=(const mystlstring &s); // operator [] overloaded reference operator[](size_type pos); const_reference operator[](size_type pos) const; private: char* data_; int length_; };
this mystlstring.cpp
#include "mystlstring.h" #include <cstring> #include <iostream> #include <stdexcept> // construct empty string(zero size , unspecified capacity). mystlstring::mystlstring():data_(nullptr), length_(0) { } // constructs string count copies of character ch. mystlstring::mystlstring(size_t count, char ch) { length_ = count; if (count == 0) { data_ = nullptr; return; } else // when count not 0 { data_ = new char[length_]; (size_t = 0; < count; ++i) { data_[i] = ch; } } } // constructs string contents initialized // copy of null-terminated character string pointed s. // length of string determined first null character. mystlstring::mystlstring(const char *s) { length_ = strlen(s); if (length_ == 0) { data_ = nullptr; return; } data_ = new char[length_]; strcpy(data_, s); } // copy constructor. // constructs string copy of contents of other. mystlstring::mystlstring(const mystlstring &s) { if (s.data_ == nullptr) { length_ = 0; data_ = nullptr; } else { length_ = strlen(s.data_); data_ = new char[length_]; strcpy(data_, s.data_); } } // destructor // free data_ pointer memory mystlstring::~mystlstring() { if (data_ != nullptr) { delete []data_; } std::cout << "length_ = " << length_ << std::endl; // test } // returns reference character @ specified location pos. // bounds checking performed, exception of type std::out_of_range thrown on invalid acess mystlstring::reference mystlstring::at(size_type pos) { if (pos >= strlen(data_)) { throw std::out_of_range("pos cross-border!\n"); } return data_[pos]; } // returns reference first character mystlstring::chart& mystlstring::front() { if (data_ == nullptr) { throw std::out_of_range("string empty!\n"); } return data_[0]; } const mystlstring::chart& mystlstring::front() const { return this->front(); } // returns reference last character mystlstring::chart& mystlstring::back() { if (data_ == nullptr) { throw std::out_of_range("string empty!\n"); } return data_[0]; } const mystlstring::chart& mystlstring::back() const { return this->back(); } // returns pointer underlying array serving character storage. // pointer such range[data(); data()+strlen(data_)] valid // in correspond values stored in string mystlstring::chart* mystlstring::data() { if (data_ == nullptr) { throw std::out_of_range("string empty!\n"); } return data_; } const mystlstring::chart* mystlstring::data() const { return this->data(); } // operator= overloaded // replace contents copy of str. // if *this , str same object, function has no effect mystlstring& mystlstring::operator=(const mystlstring &s) { // if *this , str same object, function return *this if (this == &s) { return *this; } if (s.length_ == 0) { length_ = 0; data_ = nullptr; return *this; } char* temp = s.data_; // copy *s.data_ delete data_; // free old memory data_ = new char[s.length_]; // copy data data_ member strcpy(data_, temp); length_ = s.length_; return *this; // return object } // operator[] overloaded // returns reference character @ specified location pos. // no bounds checking perfromed. mystlstring::reference mystlstring::operator[](size_type pos) { return this->at(pos); } mystlstring::const_reference mystlstring::operator[](size_type pos) const { return this->operator[](pos); }
this testmystlstring.cpp(ps: have delete other normal functions)
#include "mystlstring.h" #include <iostream> using std::cout; using std::endl; int main(void) { // test constructor convert char consequence mystlstring mystlstring s3("qwe"); return 0; }
this pic when call destructor
this pic of stack information when call destructor
const mystlstring::chart& mystlstring::front() const { return this->front(); }
will result in infinite recursion, causing stack overflow. if want re-use implementaion of non-const version, have use:
const mystlstring::chart& mystlstring::front() const { return const_cast<mystlstring*>(this)->front(); }
make same change mystlstring::back()
, mystlstring::data()
.
Comments
Post a Comment