首页 > 其他分享 ><三>关于对象优化

<三>关于对象优化

时间:2022-12-01 17:34:24浏览次数:44  
标签:对象 MyString3 rval char int pString 关于 tep 优化

代码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,避免了像左值拷贝构造一样 一次堆内存的开辟


标签:对象,MyString3,rval,char,int,pString,关于,tep,优化
From: https://www.cnblogs.com/erichome/p/16941408.html

相关文章

  • ELasticSearch优化
    硬件优化Elasticsearch的基础是Lucene,所有的素引和文档数据是存储在本地的磁盘中,具体的路径可在ES的配置文件./config/elasticsearch.yml中配置,如下:磁盘在现代服务......
  • kubernetes资源对象之security context
    一、kubernetes资源对象之securitycontextSecurityContext,即安全上下文,用于定义Pod或Container的权限和访问控制。Kubernetes提供了三种配置SecurityContext的方法:Co......
  • 将map里面Object的对象转化为指定对象
    Maven环境,先引包<dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib</artifactId><version>2.4</version><classifier>jdk15</cla......
  • CDQ 分治,李超树与斜率优化
    P4027,及一类类似问题:给定\(a_i,b_i,x_i,y_i\),对于每个\(i\)求出\(f_i=\max\limits_{j=1}^{i}\{a_ix_j+b_iy_j\}\)先说一下一类经典问题的做法:给定\(n\)个二......
  • 详解iPhone下如何获取对象一
    详解iPhone下如何获取对象教程是本文要介绍的内容,主要是讲述iPhone下如何获取对象句柄和其父对象句柄,很详细的让我们去了解iphone中的对象,先来看详细内容。常规iPhone程序对......
  • 关于粉丝迁移至本公众号的说明
    感谢您继续关注我们的公众号。您之前关注的公众号元宇宙之心MetaverseHub已经将全部业务、功能转移至本公众号。迁移详情如下:旧帐号名称:元宇宙之心MetaverseHub旧帐号主体:熵......
  • 关于c++的预定义宏
    有时候看到代码里充斥着宏,很难受,这些宏都是啥玩意,哪来的。有些是库或者代码定义的,有些是编译器定义的,有些是cmake里面定义的,再在代码里使用。查看或者说查询语言标准,编译器......
  • 关于字节大小端
    来自libhv的检验字节大小端的方法https://github.com/ithewei/libhv/blob/master/base/hendian.hstaticinlineintdetect_endian(){union{charc;......
  • 【电商】基于大数据的全球电商系统架构性能优化
    本文根据郭东白在2016ArchSummit全球架构师(深圳)峰会上的演讲整理而成。ArchSummit即将在2018年7月6日深圳华侨城洲际酒店开幕,更多分享内容请浏览:链接 讲师介绍:郭东白,现......
  • 1.类&对象&构造方法
    1.类和对象的内存处理方式1.1方法区(methodarea)也称静态区,用于存放用户定义的各个类、静态变量等。1.2堆(heap)堆中存放对象和非静态变量。在使用new关键字产生......