建立网站要多少钱,理财网站免费建设,哪些网站做任务可以赚钱,帮助传销做网站会不会判刑字符串操作是任何一个C开发程序无法绕过的点#xff0c;很多时候针对字符串的操作需要进行优化#xff0c;从而达到更优的使用效率和内存利用率。一般会采用标准的std::string替代C字符串#xff0c;一方面是std::string为一个成熟的类对象#xff0c;其成员操作基本能满足… 字符串操作是任何一个C开发程序无法绕过的点很多时候针对字符串的操作需要进行优化从而达到更优的使用效率和内存利用率。一般会采用标准的std::string替代C字符串一方面是std::string为一个成熟的类对象其成员操作基本能满足绝大多数的使用场景另一个方面是因为string在标准库中已经实现了自动的扩容操作(capacity)不用使用者再为内存空间的分配而做过多的操作从而减少对内存管理带来的性能开销。 针对string的使用不同的使用方法会带来很大的性能差距。所以在日常的开发中针对string使用方法的效率优化也是一个基础的问题。
1、传递方式优化 由于string是一个类在函数调用传递和获取string对象时如果是查询string对象的某个元素或者一些信息或者操作修改该string时采用引用传递替代值传递会减少临时对象的分配并且在同时操作多个较大的string时也会减少瞬时的内存占用突增问题。
测试代码如下
void valTransferStr(string str)
{return;
}void refTransferStr(string str)
{return;
}void testTranferStr()
{string str(test);auto current_time1 std::chrono::system_clock::now();auto timestamp1 std::chrono::duration_caststd::chrono::milliseconds(current_time1.time_since_epoch()).count();cout val begin timestamp: timestamp1 endl;for (int i 0; i 10000000; i){valTransferStr(str);}auto current_time2 std::chrono::system_clock::now();auto timestamp2 std::chrono::duration_caststd::chrono::milliseconds(current_time2.time_since_epoch()).count();cout val end timestamp: timestamp2 endl;cout val transfer string cost time: timestamp2 - timestamp1 endl;auto current_time3 std::chrono::system_clock::now();auto timestamp3 std::chrono::duration_caststd::chrono::milliseconds(current_time3.time_since_epoch()).count();cout ref begin timestamp: timestamp3 endl;for (int i 0; i 10000000; i){refTransferStr(str);}auto current_time4 std::chrono::system_clock::now();auto timestamp4 std::chrono::duration_caststd::chrono::milliseconds(current_time4.time_since_epoch()).count();cout ref end timestamp: timestamp4 endl;cout ref transfer string cost time: timestamp4 - timestamp3 endl;
} 可以看到单纯进行1000W次值传递耗时是引用耗时的52倍左右所以采用能在使用引用传递的情况尽量采用引用传递的方式。
2、扩容分配优化 针对string的扩容策略在另一篇文章中已经详细介绍过《std::string在 Windows MSVC和Linux Gcc 中capacity容量扩容策略的分析和对比》这里就不再介绍。如果需要操作的string需要频繁的进行拼接操作那么需要在代码工程定义该string的地方预先调用reserver()进行容量的分配避免频繁的capacity扩容提高运行效率。
预分配方式耗时低于反复扩容方式。
测试代码如下
void insertStr1()
{string str;for (int i 0; i 10000000; i){str 1;}
}void insertStr2()
{string str;str.reserve(10000000);for (int i 0; i 10000000; i){str 1;}
}void testInsertCostTime()
{auto current_time1 std::chrono::system_clock::now();auto timestamp1 std::chrono::duration_caststd::chrono::milliseconds(current_time1.time_since_epoch()).count();cout origin insert begin timestamp: timestamp1 endl;insertStr1();auto current_time2 std::chrono::system_clock::now();auto timestamp2 std::chrono::duration_caststd::chrono::milliseconds(current_time2.time_since_epoch()).count();cout origin insert end timestamp: timestamp2 endl;cout origin insert string cost time: timestamp2 - timestamp1 endl;auto current_time3 std::chrono::system_clock::now();auto timestamp3 std::chrono::duration_caststd::chrono::milliseconds(current_time3.time_since_epoch()).count();cout reserver insert begin timestamp: timestamp3 endl;insertStr2();auto current_time4 std::chrono::system_clock::now();auto timestamp4 std::chrono::duration_caststd::chrono::milliseconds(current_time4.time_since_epoch()).count();cout reserver insert end timestamp: timestamp4 endl;cout reserver insert string cost time: timestamp4 - timestamp3 endl;
} 3、字符拼接方式的调整
针对字符的拼接在另一篇文章中已经详细介绍过《std::string多个插入字符方式以及效率对比》。
4、遍历方式优化 直接贴上迭代器遍历以及标准的for遍历的结果
void iterLoop(string str)
{auto current_time1 std::chrono::system_clock::now();auto timestamp1 std::chrono::duration_caststd::chrono::milliseconds(current_time1.time_since_epoch()).count();cout iter loop begin timestamp: timestamp1 endl;for (auto it str.begin(); it ! str.end(); it){if (*it a){}}auto current_time2 std::chrono::system_clock::now();auto timestamp2 std::chrono::duration_caststd::chrono::milliseconds(current_time2.time_since_epoch()).count();cout iter loop end timestamp: timestamp2 endl;cout iter loop string cost time: timestamp2 - timestamp1 endl;
}void indexLoop(string str)
{auto current_time3 std::chrono::system_clock::now();auto timestamp3 std::chrono::duration_caststd::chrono::milliseconds(current_time3.time_since_epoch()).count();cout index loop begin timestamp: timestamp3 endl;auto len str.size();for (int i 0; i str.size(); i){if (str[i] a){}}auto current_time4 std::chrono::system_clock::now();auto timestamp4 std::chrono::duration_caststd::chrono::milliseconds(current_time4.time_since_epoch()).count();cout index loop end timestamp: timestamp4 endl;cout index loop string cost time: timestamp4 - timestamp3 endl;
}void testLoopStr()
{string str;for (int i 0; i 10000000; i){str.push_back(1);}iterLoop(str);indexLoop(str);
} 发现迭代器遍历执行时间大于标准for遍历但是迭代器操作不会产生临时对象这一点优于下标方式所以要看实际使用场景
5、复合赋值操作避免创建临时对象 在进行字符串拼接时字符串的连接运算符 开销会很大它会调用内存管理器构建一个临时的字符串对象来保存连接后的字符串再将该字符串赋值给目的字符串。可以采用复合赋值操作符”xxxyyy”来替代”xxx xxx yyy”的方式
测试代码如下
void testAddStr1(string str)
{string res;auto len str.size();auto current_time1 std::chrono::system_clock::now();auto timestamp1 std::chrono::duration_caststd::chrono::milliseconds(current_time1.time_since_epoch()).count();cout begin timestamp: timestamp1 endl;for (int i 0; i len; i){res res str[i];}auto current_time2 std::chrono::system_clock::now();auto timestamp2 std::chrono::duration_caststd::chrono::milliseconds(current_time2.time_since_epoch()).count();cout end timestamp: timestamp2 endl;cout string cost time: timestamp2 - timestamp1 endl;
}void testAddStr2(string str)
{string res;auto len str.size();auto current_time3 std::chrono::system_clock::now();auto timestamp3 std::chrono::duration_caststd::chrono::milliseconds(current_time3.time_since_epoch()).count();cout begin timestamp: timestamp3 endl;for (int i 0; i len; i){res str[i];}auto current_time4 std::chrono::system_clock::now();auto timestamp4 std::chrono::duration_caststd::chrono::milliseconds(current_time4.time_since_epoch()).count();cout end timestamp: timestamp4 endl;cout string cost time: timestamp4 - timestamp3 endl;
}void testAddStr()
{string str;for (int i 0; i 10000; i){str.push_back(1);}testAddStr1(str);testAddStr2(str);
} 6、减少频繁调用
举一个例子来说明当前优化点比如size()成员函数的调用。字符串的遍历为一个常见操作如果一个字符串较大在for遍历时如果每次都用当前的index与size()进行比较则需要每次都调用size()获取字符串大小调用次数为size次如果用一个临时对象先记录size大小在for遍历时就不需要进行每次的调用减少时间开销。
测试代码如下
void testCallStr1(string str)
{string res;auto current_time1 std::chrono::system_clock::now();auto timestamp1 std::chrono::duration_caststd::chrono::milliseconds(current_time1.time_since_epoch()).count();cout origin call begin timestamp: timestamp1 endl;for (int i 0; i str.size(); i){}auto current_time2 std::chrono::system_clock::now();auto timestamp2 std::chrono::duration_caststd::chrono::milliseconds(current_time2.time_since_epoch()).count();cout origin call end timestamp: timestamp2 endl;cout origin call cost time: timestamp2 - timestamp1 endl;
}void testCallStr2(string str)
{string res;auto len str.size();auto current_time3 std::chrono::system_clock::now();auto timestamp3 std::chrono::duration_caststd::chrono::milliseconds(current_time3.time_since_epoch()).count();cout opt call begin timestamp: timestamp3 endl;for (int i 0; i len; i){}auto current_time4 std::chrono::system_clock::now();auto timestamp4 std::chrono::duration_caststd::chrono::milliseconds(current_time4.time_since_epoch()).count();cout opt call end timestamp: timestamp4 endl;cout opt call cost time: timestamp4 - timestamp3 endl;
}void testStr()
{string str;for (int i 0; i 10000000; i){str.push_back(1);}testCallStr1(str);testCallStr2(str);
} 可以看到优化后的效率有所提高