问题
C 风格的字符串操作平均比库 string
类操作慢 5 倍,这是真的吗,正如 C++ Primer,第 4 版让我相信的那样?
为什么要问?
因为当我实际进行性能测试时,结果表明对于特定示例(书中使用的示例),C 风格的字符串要快大约 50%。
设置
我正在阅读 C++ Primer, 4th Edition ,其中(第 138 页)列出了以下代码:
// C-style character string implementation
const char *pc = "a very long literal string";
const size_t len = strlen(pc +1); // space to allocate
// performance test on string allocation and copy
for (size_t ix = 0; ix != 1000000; ++ix) {
char *pc2 = new char[len + 1]; // allocate the space
strcpy(pc2, pc); // do the copy
if (strcmp(pc2, pc)) // use the new string
; // do nothing
delete [] pc2; // free the memory
}
// string implementation
string str("a very long literal string");
// performance test on string allocation and copy
for(int ix = 0; ix != 1000000; ++ix) {
string str2 = str; // do the copy, automatically allocated
if (str != str2) // use the new string
; // do nothing
} // str2 is automatically freed
现在请记住,我知道第 2 行的 strlen(pc +1)
,第一个 for
使用 size_t
但没有下标数组,所以它也可能是 int
,但这正是它在书中的写法。
当我测试这段代码时(使用 strlen(pc) + 1
,我认为这是有意的),我的结果是第一个 block 的执行速度大约 50%比第二个 block ,这导致得出结论,对于这个特定示例,C 风格的字符串比库字符串类更快。
但是,我敢打赌我遗漏了一些东西(可能很明显),因为书中(第 139 页)中写的与上述代码相关的内容:
As it happens, on average, the string class implementation executes considerably faster than the C-style string functions. The relative average execution times on our more than five-year-old PC are as follows:
user 0.47 # string class
user 2.55 # C-style character string
那是哪一个呢?我应该使用更长的字符串文字吗?也许是因为他们使用的是 GNU C 编译器而我使用的是 Microsoft 的?是因为我的电脑速度更快吗?
或者这本书在这一点上错了?
编辑
Microsoft (R) 32 位 C/C++ 优化编译器版本 16.00.40219.01 for 80x86
最佳答案
您得出的结论是,对于您的编译器和机器,此示例使用 C 风格的字符串速度更快,这几乎可以肯定是因为——必须假设——你
- 忘记打开优化,
- 忘记使编译器的字符串长度“未知”(这很棘手)以防止它优化
strlen
调用,并且 - 忘记并关闭安全范围检查(如果适用),这会降低
std::string
的速度。
这是我测试过的代码:
#include <assert.h>
#include <iostream>
#include <time.h>
#include <string>
#include <string.h>
using namespace std;
extern void doNothing( char const* );
class StopWatch
{
private:
clock_t start_;
clock_t end_;
bool isRunning_;
public:
void start()
{
assert( !isRunning_ );
start_ = clock();
end_ = 0;
isRunning_ = true;
}
void stop()
{
if( isRunning_ )
{
end_ = clock();
isRunning_ = false;
}
}
double seconds() const
{
return double( end_ - start_ )/CLOCKS_PER_SEC;
}
StopWatch(): start_(), end_(), isRunning_() {}
};
inline void testCStr( int const argc, char const* const argv0 )
{
// C-style character string implementation
//const char *pc = "a very long literal string";
const char *pc = (argc == 10000? argv0 : "a very long literal string");
//const size_t len = strlen(pc +1); // space to allocate
const size_t len = strlen(pc)+1; // space to allocate
// performance test on string allocation and copy
for (size_t ix = 0; ix != 1000000; ++ix) {
char *pc2 = new char[len + 1]; // allocate the space
strcpy(pc2, pc); // do the copy
if (strcmp(pc2, pc)) // use the new string
//; // do nothing
doNothing( pc2 );
delete [] pc2; // free the memory
}
}
inline void testCppStr( int const argc, char const* const argv0 )
{
// string implementation
//string str("a very long literal string");
string str( argc == 10000? argv0 : "a very long literal string" );
// performance test on string allocation and copy
for(int ix = 0; ix != 1000000; ++ix) {
string str2 = str; // do the copy, automatically allocated
if (str != str2) // use the new string
//; // do nothing
doNothing( &str2[0] );
} // str2 is automatically freed
}
int main( int argc, char* argv[] )
{
StopWatch timer;
timer.start(); testCStr( argc, argv[0] ); timer.stop();
cout << "C strings: " << timer.seconds() << " seconds." << endl;
timer.start(); testCppStr( argc, argv[0] ); timer.stop();
cout << "C++ strings: " << timer.seconds() << " seconds." << endl;
}
典型结果:
[d:\dev\test] > g++ foo.cpp doNothing.cpp -O2 [d:\dev\test] > a C strings: 0.417 seconds. C++ strings: 0.084 seconds. [d:\dev\test] > a C strings: 0.398 seconds. C++ strings: 0.082 seconds. [d:\dev\test] > a C strings: 0.4 seconds. C++ strings: 0.083 seconds. [d:\dev\test] > _
也就是说,C++ 字符串通常不是最快的字符串实现。
通常,不可变字符串(引用计数)以很大的优势击败 C++ 字符串,而且,当我了解到这一点时,令我惊讶的是,当它使用适当、快速的自定义时,简单地复制字符串数据的字符串实现仍然更快分配器。但是,不要问我如何实现后者。我只在另一个论坛上看到了代码和测试结果,这是我在与 STL 的讨论中指出不可变字符串的普遍优势并且存在一些分歧后有人慷慨地提供的。 ;-)
关于c++ - C 风格字符串与库字符串性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11165237/