C++代码优化,提升性能★★★

1.——使用string的append()代替+=

1.背景

背景:部分代码中对于string字符串的添加采用+=方式,经测验,append方式执行效率更高。

2.测验代码

#include<iostream> 
#include<ctime> 
#include<map> 
using namespace std; 
int main() {                  
for (int j = 0; j < 10; ++j) {                
   string strinfo;                
   clock_t startTime, endTime;                
   startTime = clock();//计时开始                
   for (long int i = 0; i < 20000000; i++) {                        
    //strinfo += "大家好!";                        
    strinfo.append("本次活动为:");               
 }                
   endTime = clock();//计时结束                
   cout << "The run time is: " << (double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl;         }         
system("pause");         
return 0; }


(1)使用append

(2)使用+=

3.原因basic_string.h:源码探究

 //-------------------------------+=运算符重载部分---------------------------
//追加 string 类型字符串
 basic_string&
 operator+=(const basic_string& __str)		
 { return this->append(__str); }

//追加 cstring 类型字符串
 basic_string&
 operator+=(const _CharT* __s)				
 { return this->append(__s); }

//追加单个字符
 basic_string&
 operator+=(_CharT __c)						
 { 
	this->push_back(__c);
	return *this;
 }

#if __cplusplus >= 201103L
    
//追加字符类型的初始化列表
 basic_string&
 operator+=(initializer_list<_CharT> __l)		
 { return this->append(__l.begin(), __l.size()); }
 
//-------------------------------append函数实现部分---------------------------

//追加 string 类型字符串
 basic_string&
 append(const basic_string& __str);			

//追加部分 string 类型字符串
 basic_string&								
 append(const basic_string& __str, size_type __pos, size_type __n);

//追加部分 cstring 类型字符串
 basic_string&								
 append(const _CharT* __s, size_type __n);

//追加 cstring 类型字符串
 basic_string&								
 append(const _CharT* __s)
 {
	__glibcxx_requires_string(__s);
	return this->append(__s, traits_type::length(__s));
 }

//追加多个字符
 basic_string&							
 append(size_type __n, _CharT __c);

#if __cplusplus >= 201103L

//追加字符类型的初始化列表
 basic_string&							
 append(initializer_list<_CharT> __l)
 { return this->append(__l.begin(), __l.size()); }
 
#endif // C++11

 template<class _InputIterator>
 basic_string&							//附加给定范围内的多个字符
 append(_InputIterator __first, _InputIterator __last)
 { return this->replace(_M_iend(), _M_iend(), __first, __last); }

可以看到+=部分代码为:

operator+=(const basic_string& __str) {               
    return this->append(__str); 
}

所以+=本质还是调用的append,只不过是运算符重载。
4.结果建议代码后续采用append方式代替+=,从而提升服务器运行效率

参考资料:

  1. C++的string类型中关于append函数、push_back函数和+=运算符的区别 - 阿KUN呐 - 博客园

2.——映射使用unordered_map代替map

1.背景

背景:项目代码中对于命令映射采用map方式,经测验,unordered_map方式执行效率更高。


2.测验代码

#include<iostream>
#include<ctime>
#include<map>
#include<unordered_map>
using namespace std;
//         map<string, int> m_mCmdName;           //命令映射表
         unordered_map<string, int> m_mCmdName;           //命令映射表


void SetCommandMap()
{
	m_mCmdName["1"] = 1;
	m_mCmdName["2"] = 2;
	m_mCmdName["3"] = 3;
	m_mCmdName["4"] = 5;
	m_mCmdName["6"] = 6;
	m_mCmdName["6"] = 6;
	m_mCmdName["7"] = 6;
	m_mCmdName["8"] = 6;
	m_mCmdName["9"] = 6;
	m_mCmdName["10"] = 6;
	m_mCmdName["11"] = 6;
	m_mCmdName["12"] = 6;
	m_mCmdName["13"] = 6;
	m_mCmdName["14"] = 6;
	m_mCmdName["15"] = 6;
	m_mCmdName["15"] = 6;
	m_mCmdName["16"] = 6;
	m_mCmdName["17"] = 6;
	m_mCmdName["18"] = 6;
	m_mCmdName["19"] = 6;
	m_mCmdName["20"] = 6;
}

int main()
{
	SetCommandMap();
	int a;
	for (int j = 0; j < 10; ++j) {
		string strinfo;
		clock_t startTime, endTime;
		startTime = clock();//计时开始
		for (long int i = 0; i < 1000000; i++) {
			a= m_mCmdName["20"] ;			
		}
		endTime = clock();//计时结束
		cout << "The run time is: " << (double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl;

	}
	system("pause");
	return 0;

}

<1>在哈希表只有5个元素的情况下(1)使用map(2)使用unordered_map

<2>在哈希表表有20个元素的情况下

结论:可以发现,平均运行时间unordered_map更快,unordered_map效率是map的两倍,使用unordered_map可以将效率提升100%。

3.原因

basic_string.h:源码探究map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。 

unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。

4.优缺点以及适用处:

1.map:

优点:有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作  红黑树,内部实现一个红黑书使得map的很多操作在lgn的时间复杂度下就可以实现,因此效率非常的高  缺点: 空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间

适用处:对于那些有顺序要求的问题,用map会更高效一些

2.unordered_map:

优点: 因为内部实现了哈希表,因此其查找速度非常的快 

缺点: 哈希表的建立比较耗费时间  适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map  总结:

内存占有率的问题就转化成红黑树 VS hash表 , 还是unorder_map占用的内存要高。  但是unordered_map执行效率要比map高很多  对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的。

 map和unordered_map的使用

 unordered_map的用法和map是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。其底层实现是完全不同的,上方已经解释了,但是就外部使用来说却是一致的。

4.结果运行效率方面:unordered_map最高,hash_map其次,而map效率最低

占用内存方面:hash_map内存占用最低,unordered_map其次,而map占用最高

结论:

  • map是基于红黑树结构实现的。红黑树是一种平衡二叉查找树的变体结构,它的左右子树的高度差有可能会大于 1。所以红黑树不是严格意义上的平衡二叉树AVL,但对之进行平衡的代价相对于AVL较低, 其平均统计性能要强于AVL。红黑树具有自动排序的功能,因此它使得map也具有按键(key)排序的功能,因此在map中的元素排列都是有序的。在map中,红黑树的每个节点就代表一个元素,因此实现对map的增删改查,也就是相当于对红黑树的操作。对于这些操作的复杂度都为O(logn),复杂度即为红黑树的高度。
  • unordered_map是基于哈希表(也叫散列表)实现的。散列表是根据关键码值而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。散列表使得unordered_map的插入和查询速度接近于O(1)(在没有冲突的情况下),但是其内部元素的排列顺序是无序的。

在需要元素有序性或者对单次查询性能要求较为敏感时,请使用map,其余情况下应使用unordered_map。

unordered_map效率是map的两倍,使用unordered_map可以将效率提升100%。

建议代码后续采用unordered_map方式代替map,从而提升服务器运行效率

参考资料:

  1. https://blog.csdn.net/qq_21997625/article/details/84672775

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值