这样使用字符串是低效的吗?
Is using strings this way inefficient?
我是c++的新手,在我的代码中遇到了我的老师使用字符串的问题。虽然我很清楚,我必须在她的课上停止这样做,但我很好奇为什么这是错的。在这个程序中,我分配的五个字符串将被重用不少于4到5次,因此我将文本放入字符串中。我被告知停止这样做,因为它效率低下。为什么?在c++中,文本字符串应该被输入而不是存储在字符串中,如果是这样,为什么?下面是一些程序,请告诉我为什么它不好。
string Bry = "berries";
string Veg = "vegetables";
string Flr = "flowers";
string AllStr;
float Tmp1, Precip;
int Tmp, FlrW, VegW, BryW, x, Selct;
bool Cont = true;
AllStr = Flr + ", " + Bry + ", " + "and " + Veg;
回答使用字符串是否效率低下实际上在很大程度上取决于你如何使用它们
首先,我认为你应该使用c++字符串作为默认值——只有当你实际测量并发现c++字符串太慢时才使用原始的C字符串。它的优势(主要是为了安全性)实在是太大了——用原始C字符串搞砸缓冲区管理太容易了。所以我不同意你老师的观点,认为这是过于低效的。也就是说,理解使用c++字符串的性能含义是很重要的。由于它们总是动态分配的,因此最终可能会花费大量时间复制和重新分配缓冲区。这通常不是问题;通常还有其他事情占用更多的时间。但是,如果在对程序性能至关重要的循环中执行此操作,则可能需要寻找另一种方法。
简而言之,过早的优化通常是一个坏主意。编写明显正确的代码,即使运行时间稍微长一点。但同时也要意识到你所付出的代价和权衡;这样,如果c++字符串实际上使你的程序慢了很多,你就会知道该怎么做来解决这个问题。
是的,它相当低效,原因如下:
- 当您构造一个
std::string
对象时,它必须为字符串内容分配一个存储空间(这可能是也可能不是一个单独的动态内存分配,取决于小字符串优化是否有效),并复制作为构造函数参数的文字字符串。例如,当您说:string Bry = "berries"
时,它分配一个单独的内存块(可能来自动态内存),然后将"浆果"复制到该块。- 所以你可能有一个额外的动态内存分配(花费时间),
- 必须执行复制(花费更多时间),
- 并以相同字符串的2个副本结束(占用空间)。
std::string::operator+
产生一个新的字符串,这是连接的结果。因此,当您在一行中编写几个+
操作符时,您有几个临时连接结果和许多不必要的复制。对于你的例子,我建议:
- 使用字符串字量,除非您确实需要
std::string
中提供的功能。 - 使用
std::stringstream
将多个字符串连接在一起
通常,代码的可读性比这种类型的微优化更受欢迎,但幸运的是,在这种情况下,您可以同时获得性能和可读性。
你的老师是对的也是错的。S/he是对的,在运行时从子字符串构建字符串比简单地在代码中提供完全预先构建的字符串更低的cpu效率——但他/他认为效率在这种情况下是一个必须考虑的重要因素,这是错误的。
在很多情况下,效率根本不重要。在所有。例如,如果上面的代码只会很少执行(例如每秒不超过一次),那么就不可能测量"最有效的版本"和不那么有效的版本之间的任何差异。考虑到这一点,决定其他因素(如代码可读性和可维护性)比最大化效率更重要是很有道理的。
当然,如果你的程序每秒要重构这些字符串数千次或数百万次,那么确保你的代码最大限度地高效,即使以牺牲可读性/可维护性为代价,也是一个很好的权衡。但我对这里的情况表示怀疑。
您的方法几乎是完美的-尝试只声明一次所有内容。但是如果它不被使用超过一次-不要浪费你的手指输入它:-)例如一个10行程序
我建议的唯一改变是使字符串为const,以帮助编译器优化你的程序。
如果你的教练仍然不同意,那就换一个新的教练。
效率很低。如果最后一行写对了,速度会提高4-5倍。
至少应该使用+=
+=意味着可以避免使用+操作符创建新的字符串。
教师知道,当您执行string = string + string时,c++将创建一个立即销毁的新字符串。
效率可能不是在学校作业中不使用字符串的好理由,但是,如果我是一名教师,并且主题不是关于一些非常高级的应用程序,我不希望我的学生使用字符串。
真正的原因是字符串隐藏了底层的内存管理。一个刚从大学毕业的学生应该具备基本的记忆管理技能。虽然现在在工作环境中,程序员在大多数时间都不处理内存管理,但总有一些情况需要了解底层发生了什么,以便能够对遇到的问题进行推理。
有了给定的上下文,看起来您应该能够将AllString声明为const或字符串字面量,而不需要所有的子字符串和加法。假设还有更多,将它们声明为文字string
对象在运行时分配内存。(这里并不是说有任何实际影响,但您应该意识到,stl容器对象有时会分配一个默认的最小空间,这个空间比最初在其中的事物数量要大,这是预期以后修改操作的优化的一部分。)我不确定std::string是否在声明/赋值上这样做。如果您只打算将它们作为文字使用,那么将它们声明为const char*
或#define
对于内存和运行时性能都更容易,并且您仍然可以在string
操作中将它们用作r值。如果你在代码中以其他方式使用它们而没有向我们展示,那么就取决于它们是否需要更改或操纵,以及它们是否需要成为string
s。
如果你正在尝试学习编码,那么在实践中无关紧要的低效率仍然是你应该意识到并避免的事情。在产品代码中,有时会有这样做的理由,但如果不是出于任何好的理由,那就太草率了。她指出这一点是对的,但她应该做的是把这一点作为一个起点,讨论涉及到的各种权衡——内存、速度、可读性、可维护性等等。如果她是老师,她应该寻找这样的"教学时刻",而不仅仅是一个责骂的机会。
可以使用string.append();它比+或+=