【发布时间】:2010-10-12 20:50:52
【问题描述】:
我发现std::strings 与老式的以空字符结尾的字符串相比非常慢,非常慢,以至于它们显着使我的整个程序减慢了 2 倍。
我预计 STL 会更慢,但我没有意识到它会慢这么多。
我使用的是 Visual Studio 2008,发布模式。它显示字符串的分配比char* 分配慢100-1000 倍(测试char* 分配的运行时间非常困难)。我知道这不是一个公平的比较,指针分配与字符串复制,但我的程序有很多字符串分配,我不确定我是否可以在所有地方使用“const reference”技巧。使用引用计数实现,我的程序会很好,但这些实现似乎不再存在了。
我真正的问题是:为什么人们不再使用引用计数实现,这是否意味着我们都需要更加小心避免 std::string 的常见性能缺陷?
我的完整代码如下。
#include <string>
#include <iostream>
#include <time.h>
using std::cout;
void stop()
{
}
int main(int argc, char* argv[])
{
#define LIMIT 100000000
clock_t start;
std::string foo1 = "Hello there buddy";
std::string foo2 = "Hello there buddy, yeah you too";
std::string f;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
f = foo1;
foo1 = foo2;
foo2 = f;
}
double stl = double(clock() - start) / CLOCKS\_PER\_SEC;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
}
double emptyLoop = double(clock() - start) / CLOCKS_PER_SEC;
char* goo1 = "Hello there buddy";
char* goo2 = "Hello there buddy, yeah you too";
char *g;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
g = goo1;
goo1 = goo2;
goo2 = g;
}
double charLoop = double(clock() - start) / CLOCKS_PER_SEC;
cout << "Empty loop = " << emptyLoop << "\n";
cout << "char* loop = " << charLoop << "\n";
cout << "std::string = " << stl << "\n";
cout << "slowdown = " << (stl - emptyLoop) / (charLoop - emptyLoop) << "\n";
std::string wait;
std::cin >> wait;
return 0;
}
【问题讨论】:
-
如果 char* 指针副本对您有用(即,如果不需要深拷贝),那么 std::string* 指针副本也是如此。所以使用它们。没有人说你不允许混合指针和 std::strings。与 char* 一样,您需要确保所指向的对象在您使用它们时保持活动状态。
-
@Tim Cooper,您实际上并没有复制这些 C 字符串。您复制的是句柄(指针),而不是它们指向的数据。它相当于在 std::string 上使用 swap。
-
蒂姆·库珀。尝试像这样循环测量尺寸。 strlen vs str.size() 我敢打赌你会看到 std::string 至少快 3 倍 :)
-
@TimCooper 这是一种完全错误的思考方式。与任何其他对象一样,使用指向 std::string 或任何其他 C++ 对象的指针或引用或智能指针非常好(只要它们不拥有内存,原始指针就非常好)。您还可以廉价地交换两个字符串的内容(string::swap),这是指针的浅交换。如果您使用任何 C++ 对象,则默认行为是 复制。这不是类的问题,这是因为默认情况下,C++ 对象模型可复制的值类型,而不是引用类型。如果你想要一个引用或指向 ...
-
@TimCooper 也避免一起使用 C++ 并坚持使用 C,否则你可以对任何对象提出相同的论点:向量、列表、字符串、QT 小部件,如果你认为因为此类事物的默认行为是深复制意味着您可以仅深复制,那么您将永远不会编写非常高效的 C++ 代码。对于 C++ 开发人员而言,编写性能关键代码以了解在何处进行深度复制以及如何避免不必要的复制以及能够区分使用堆栈和堆的内容是至关重要的。
标签: c++ stl performance