tmp
我想知道是否可以在下面的代码中重用字符串内存。它的内存是否在每次迭代中重新分配?有没有更好的方法来处理这种情况?
string s, line;
map<string, string> mymap;
while(getline(file, line) {
if(a) s = "_a";
else if(b) s = "_b";
string tmp = line + s;
mymap.insert(tmp, s);
}
tmp
我想知道是否可以在下面的代码中重用字符串内存。它的内存是否在每次迭代中重新分配?有没有更好的方法来处理这种情况?
string s, line;
map<string, string> mymap;
while(getline(file, line) {
if(a) s = "_a";
else if(b) s = "_b";
string tmp = line + s;
mymap.insert(tmp, s);
}
tmp
每次在循环周围创建和销毁,并在line
. 因此,您可以像这样获得便宜的可能改进并且几乎不会变得更糟:
if(a) s = "_a";
else if(b) s = "_b";
line += s;
mymap.insert(line, s);
我还会给出s
类型:为每个循环分配一次仅包含文字副本的循环const char*
并没有多大意义。string
但它确实string
通过调用转换为insert
,所以无论哪种方式都没有太多。
只要您不破坏代码的简单性/可读性/可维护性/设计来实现它,可能的改进和几乎不会变得更糟并不是过早的优化。line
和的范围越大s
,玩弄它们的风险就越大(分别改变值和改变类型),因为您可能会以某种方式误导读者/维护者。这是短函数很好的原因之一。
在 C++11 中,您可以编写mymap.insert(std::move(line), s);
另一个简单的可能改进。
综上所述:您可能会发现,无论您做了多少不必要的复制和分配,所花费的时间与getline
. 在这种情况下,有两种非常相似的代码编写方式,其中一种“应该”更有效。所以你不妨使用它,但不要高估它,认为它一定会有所作为。
while 循环的每次迭代都会创建和销毁您的字符串tmp
对象。因此,正如已经建议的那样,第一步是移出tmp
while 循环。这样您就不必每次迭代都构造一个新的字符串对象。但是,您仍然有tmp = line + s
每次迭代都会导致内存重新分配的分配。使用 = 运算符创建参数的副本,并将副本分配给 tmp 字符串对象。因此,第二步是添加删除字符串对象mymap.insert(line+s, s);
的需要的建议。tmp
我认为人们可以通过不分配"_a"
或在每次迭代"_b"
中字符串来继续这种改进。s
这可以在while循环之外完成一次,然后根据内容a
和b
不同的字符串对象可以添加到您的地图中。像这样的东西(注意这是未经测试的):
string a = "_a";
string b = "_b";
string line;
map<string, string> mymap;
while(getline(file, line) {
if(a) mymap.insert(line+a, a);
else if(b) mymap.insert(line+b, b);
}
有人可能会争论这是否很好,我认为 juanchopanza 的答案就足够了,因为它保持了代码的可读性。但我认为上面的代码制作的副本更少。
是的,使用 C++ 11 标准中引入的 STD::MOVE 语义。
更新:示例
#include <iostream>
#include <utility>
#include <vector>
#include <string>
int main()
{
std::string str = "Hello";
std::vector<std::string> v;
// uses the push_back(const T&) overload, which means
// we'll incur the cost of copying str
v.push_back(str);
std::cout << "After copy, str is \"" << str << "\"\n";
// uses the rvalue reference push_back(T&&) overload,
// which means no strings will copied; instead, the contents
// of str will be moved into the vector. This is less
// expensive, but also means str might now be empty.
v.push_back(std::move(str));
std::cout << "After move, str is \"" << str << "\"\n";
std::cout << "The contents of the vector are \"" << v[0]
<< "\", \"" << v[1] << "\"\n";
}