我想知道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);
}
答案 0 :(得分:4)
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
中的I / O时间相比相形见绌。在这种情况下,有两种非常类似的编写代码的方法,其中一种“应该”更有效。所以你不妨使用它,但不要过度重视它,因为它认为它必然会产生影响。
答案 1 :(得分:3)
while循环的每次迭代都将创建并销毁字符串tmp
对象。因此,第一步是将tmp
移出while循环,如前所述。这样您就不必每次迭代都构造一个新的字符串对象。但是,您仍然需要tmp = line + s
赋值,这会导致每次迭代重新分配内存。使用=运算符创建参数的副本,并将副本分配给tmp字符串对象。因此,第二步是添加建议的mymap.insert(line+s, s);
,以消除对tmp
字符串对象的需要。
我认为可以通过在每次迭代时不将"_a"
或"_b"
分配给字符串s
来继续这种改进。这可以在while循环之外完成一次,然后根据a
和b
的内容,可以将不同的字符串对象添加到地图中。像这样(n.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的答案就足够了,因为它保持了代码的可读性。但我认为上面的代码制作的副本较少。
答案 2 :(得分:1)
是的,使用在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";
}