1

我今天正在玩一些计时代码,发现当将字符串文字分配给 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 一样编写它?

4

2 回答 2

4

第一个无法优化为第二个。第一个,字符串的长度是未知的,所以必须计算,第二个你告诉它有多长,所以不需要计算。

并且使用 sizeof() 没有区别 - 这也是在编译时计算的。第一种情况使用的构造函数是:

 string( const char * s );

这个构造函数无法检测到它被赋予了一个字符串文字,更不用说在编译时计算它的长度了。

此外,从 C 风格的字符串文字构造字符串在实际代码中相对很少发生 - 它根本不值得优化。如果您确实需要优化它,只需重新编写:

while( BIGLOOP ) {
   string s( "foobar" );
   ...
}

作为:

string f( "foobar" );
while( BIGLOOP ) {
   string s( f );
   ...
}
于 2010-01-31T23:00:06.863 回答
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;
}

一个很大的缺点是每个不同的字符串大小都会生成一个函数/构造函数的版本,如果编译器不能很好地处理模板提升,整个类甚至可能被复制......这些可能在某些情况下会破坏交易情况。

于 2010-02-01T03:30:48.193 回答