对象化的活动(关于对象优化)
导读:代码1 #...
代码1
#include <iostream> using namespace std; class MyString3 { public: MyString3(const char * pChar=nullptr) { if (pChar == nullptr) { this->pString = new char[1]; this->pString[0] = \0; } else { int len = strlen(pChar); this->pString = new char[len + 1]; strcpy(this->pString, pChar); } cout << "MyString 构造函数" << endl; } // 左值拷贝构造 MyString3(const MyString3 & _rval) { int len = strlen(_rval.pString); this->pString = new char[len + 1]; strcpy(this->pString, _rval.pString); cout << "MyString 左值拷贝构造函数" << endl; } //左值赋值重载函数 MyString3 & operator =(const MyString3 & _rval) { cout << "MyString 左值赋值重载函数" << endl; if (this == &_rval) { return *this; } else { delete[]this->pString; this->pString = nullptr; int len = strlen(_rval.pString); char *tep = new char[len + 1]; strcpy(tep,_rval.pString); this->pString = tep; return *this; } } const char * c_str() { return pString; } ~MyString3() { cout << "MyString 析构函数" << endl; delete[] this->pString; pString = nullptr; } private: char *pString; }; MyString3 getMyString(MyString3 & ms) { const char * tep = ms.c_str(); MyString3 S(tep); return S; } int main() { MyString3 S1("ABCDEF123456"); MyString3 S2; S2=getMyString(S1); system("pause"); return 0; }上面出现大量重复的空间开辟和析构过程.
如何解决上面的问题?
先回顾一下以前关于左值引用,和右值引用 int a =10; int & ra=a; 左值,有名字 ,有地址 如a ,可以将左值引用绑定到一个左值上 int &b =100;//错误 不能将左值引用绑定到一个右值,100是右值 右值:没有名字,没有地址 int &&rb=100;//ok 将右值引用绑定到 右值 int &&rb=a;//错误,不能将右值引用绑定到左值 int &b =100 //错误, 如果要想可以 需要 const int &b =100; 编译器其实生成了一个 临时量 int tep=100; int &b=tep; 同理 // 不可以,因为C++编译器将匿名对象都看做右值,所以要 MyString3 && rs=MyString3;或者 const MyString3 &s=MyString3; MyString3 &s=MyString3("ABC");代码2
#include <iostream> using namespace std; class MyString3 { public: MyString3(const char * pChar=nullptr) { if (pChar == nullptr) { this->pString = new char[1]; this->pString[0] = \0; } else { int len = strlen(pChar); this->pString = new char[len + 1]; strcpy(this->pString, pChar); } cout << "MyString 构造函数" << endl; } // 左值拷贝构造 MyString3(const MyString3 & _rval) { int len = strlen(_rval.pString); this->pString = new char[len + 1]; strcpy(this->pString, _rval.pString); cout << "MyString 左值拷贝构造函数" << endl; } // 右值拷贝构造, MyString3 && _rval 这个形参,右值引用 匹配 的是 临时对象 MyString3(MyString3 && _rval) { //由于临时对象声明周期 只在当前语句,出了当前语句就销售了 //所以我们可以复用他开辟的堆空间,避免重复开辟 this->pString = _rval.pString; _rval.pString = nullptr;//要置空,避免多个MyString 对象指向同一个堆空间 cout << "MyString 右值拷贝构造函数" << endl; } //左值赋值重载函数 MyString3 & operator =(const MyString3 & _rval) { cout << "MyString 左值赋值重载函数" << endl; if (this == &_rval) { return *this; } else { delete[]this->pString; this->pString = nullptr; int len = strlen(_rval.pString); char *tep = new char[len + 1]; strcpy(tep,_rval.pString); this->pString = tep; return *this; } } //右值赋值重载函数 MyString3 && _rval 这个形参,右值引用 匹配 的是 临时对象 MyString3 & operator =(MyString3 && _rval) { cout << "MyString 右值赋值重载函数" << endl; if (this == &_rval) { return *this; } else { //由于临时对象声明周期 只在当前语句,出了当前语句就销售了 //所以我们可以复用他开辟的堆空间,避免重复开辟 this->pString = _rval.pString; _rval.pString = nullptr;//要置空,避免多个MyString 对象指向同一个堆空间 return *this; } } const char * c_str() { return pString; } ~MyString3() { cout << "MyString 析构函数" << endl; delete[] this->pString; pString = nullptr; } private: char *pString; }; MyString3 getMyString(MyString3 & ms) { const char * tep = ms.c_str(); MyString3 S(tep); return S; } int main() { MyString3 S1("ABCDEF123456"); MyString3 S2; S2=getMyString(S1); system("pause"); return 0; }
通过右值引用,避免了一些内存重复开辟
代码3
MyString3 operator +(const MyString3 & ls,const MyString3 rs) { char * tp = new char[strlen(ls.pString) + strlen(rs.pString) + 1]; strcpy(tp, ls.pString); strcat(tp, rs.pString); return MyString3(tp); } ostream & operator <<(ostream &out, const MyString3 & s) { cout << s.c_str() << endl; return out; } int main() { MyString3 S1("ABCDEF"); MyString3 S2=("1234"); MyString3 S3 = S1 + S2; cout << S3 <<"S3地址 ="<<&S3 << endl; system("pause"); return 0; } 在MyString 中加入 + 法操作,上面的 operator +()函数有问题, tp 没有 delete 内存泄漏了 修改如下 MyString3 operator+ (const MyString3 & ls, const MyString3 & rs) { char * tp = new char[strlen(ls.pString) + strlen(rs.pString) + 1]; strcpy(tp, ls.pString); strcat(tp, rs.pString); MyString3 ts(tp); delete[]tp; cout << " operato + " << endl; return ts; } //修改完成后 tp 指针能正常释放内存, 但是多构建了MyString3 ts(tp);对象,继续优化 ,执行结果如下第二张图 MyString3 operator+ (const MyString3 & ls, const MyString3 & rs) { MyString3 ts; ts.pString= new char[strlen(ls.pString) + strlen(rs.pString) + 1]; strcpy(ts.pString, ls.pString); strcat(ts.pString, rs.pString); cout << " operato + " << endl; return ts; } MyString3 S3 = S1 + S2; //operator+ 返回的ts对象会使用 右值拷贝构造创建 S3,避免了像左值拷贝构造一样 一次堆内存的开辟创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!