我今天玩了一些计时代码并发现当将一个字符串文字与std :: string一起使用时,它的速度提高了大约10%(使用一个短的12个字符串字符串,因此大字符串的差异更大)使用已知长度的文字(使用sizeof运算符)而不是。 (仅使用VC9编译器进行测试,因此我猜其他编译器可能会做得更好)。
std::string a("Hello World!");
std::string b("Hello World!", sizeof("Hello World!");//10% faster in my tests
现在我怀疑的原因是它必须调用strlen(VC9进入汇编,这不是我的强点所以我不能100%肯定)来获取字符串长度,然后像第二种情况一样无论如何。
考虑到std :: string已经存在了多长时间,以及在实际程序中第一种情况(特别是如果你包括+,=,+ =等操作符和等效方法)有多常见,为什么它不会优化第一种情况进入第二种情况?这似乎是一个非常简单的,只要说它是一个std :: basic_string对象和一个文字,编译它就好像它被写成b?
答案 0 :(得分:4)
第一个无法优化到第二个。在第一个,字符串的长度是未知的,因此必须计算,在第二个你告诉它多长时间,所以不需要计算。
使用sizeof()没有区别 - 这也是在编译时计算的。第一种情况使用的构造函数是:
string( const char * s );
这个构造函数无法检测到它是否被赋予字符串文字,更不用说在编译时计算它的长度了。
此外,在实际代码中,从C风格的字符串文字构造字符串相对较少 - 它根本不值得优化。如果你确实需要优化它,只需重写:
while( BIGLOOP ) {
string s( "foobar" );
...
}
为:
string f( "foobar" );
while( BIGLOOP ) {
string s( f );
...
}
答案 1 :(得分:2)
编译器无疑可以做到这样的事情,实际上你可以自己做:
template<size_t SIZE>
std::string f(const char(&c)[SIZE]) {
return std::string(c, SIZE);
}
int main() {
std::string s = f("Hello");
cout << s;
}
或甚至使用自定义派生类型(尽管std :: string没有理由不能使用此构造函数):
class mystring : public string {
public:
template<size_t SIZE>
mystring(const char(&c)[SIZE]) : string(c, SIZE) {}
};
int main() {
mystring s("Hello");
cout << s;
}
一个很大的缺点是为每个不同的字符串大小生成了一个函数/构造函数的版本,如果编译器不能很好地处理模板提升,整个类甚至可以复制......这些可能是交易 - 在某些情况下会破坏。