创建一个空的std::string对象有多种方式,常见的有以下两种:
第一种是直接使用std::string的默认构造函数,例如:
1 2 3 4 5 6 7
| std::string string;
std::string GetEmptyString() { return std::string(); }
|
第二种是由空的C字符串字面量转换,不论是显式的还是隐式的转换,例如:
1 2 3 4 5 6 7 8
| std::string string1(""); std::string string2 = "";
std::string GetEmptyString() { return ""; }
|
这两种方式的结果都是一样的,但是过程却有一点不同。第一种方式直截了当地创建一个空std::string对象,没有多余的操作;而第二种方式则多了一个转换过程——它要通过strlen之类的函数计算出字符串的长度。即便是空字符串,这个转换过程也会造成一些开销。所以,从理论上来说,第二种方式的性能会比较差。具体差了多少呢?可以使用以下代码进行测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <iostream> #include <sstream> #include <string>
int main() {
const int Count = 100000000;
std::ostringstream os;
std::clock_t begin_time = clock();
for (int count = 0; count < Count; ++count) { std::string str; os << str; }
std::clock_t end_time = clock(); std::cout << double(end_time - begin_time) / CLOCKS_PER_SEC << std::endl;
begin_time = clock();
for (int count = 0; count < Count; ++count) { std::string str(""); os << str; }
end_time = clock(); std::cout << double(end_time - begin_time) / CLOCKS_PER_SEC << std::endl; std::cout << os.str() << std::endl; }
|
分别用两种方式创建std::string对象一亿次,输出两者的耗时。每次创建字符串之后,都会把它输出到一个std::ostringstream对象中,这是为了避免在release模式下编译器把无实际作用的for循环优化掉。以下是在XCode中运行的输出结果:
1.47766
1.97115
可见,第二种方式确实会比第一种方式慢,不过差距十分微小:在创建一亿个std::string对象的级别下才慢了0.5秒,几乎可以忽略不计。尽管如此,对于追求效率的程序员来说,显然第一种方式更胜一筹。