假设我实现了以下两种字符串反转算法:
void reverse(string &s) {
if(s.size() == 1) return;
string restOfS = s.substr(1);
reverse(restOfS);
s = restOfS + s.at(0);
}
string reverseString(string s) {
if(s.size() == 1) return s;
return reverseString(s.substr(1)) + s.at(0);
}
int main() {
string name = "Dominic Farolino";
reverse(name);
cout << name << endl;
name = reverseString(name);
cout << name << endl;
return 0;
}
其中一个显然修改了赋予它的字符串,其中一个返回一个新字符串。由于第一个修改给定字符串并使用引用参数作为其与下一个递归堆栈帧的通信模式,我首先假设这将更有效,因为使用引用参数可以帮助我们不复制内存中的内容但是,我不相信这种情况。显然我们必须使用带有void
函数的引用参数,但似乎我们正在使用引用参数撤消任何内存效率,因为我们只是每次在堆栈上声明一个新变量。
简而言之,似乎第一个是每个调用都复制一个引用,第二个是每个调用复制一个值,只返回它的结果,使它们具有相同的内存消耗。
为了让第一个内存更有效,我觉得你必须做这样的事情:
void reverse(string &s) {
if(s.size() == 1) return;
reverse(s.substr(1));
s = s.substr(1) + s.at(0);
}
然而编译器不会让我:
error: invalid initialization of non-const reference of type 'std::string& {aka std::basic_string<char>&}' from an rvalue of type 'std::basic_string<char>'
6:6: note: in passing argument 1 of 'void reverse(std::string&)'
这种分析是否正确?
答案 0 :(得分:3)
substr()
每次都会返回一个 new 字符串,并附带所有内存使用情况。因此,如果您要N-1
拨打substr()
来O(N^2)
,那么您将无缘无故地使用该std::string
个额外内存。
虽然使用for
,但您可以使用简单的void reverseString(string &s) {
std::reverse(s.begin(), s.end());
}
循环对其进行迭代,从而对其进行修改。或者只使用std::reverse
:
for
无论哪种方式(O(1)
循环或算法)都需要swap
额外的内存 - 它实际上只是一系列char
s,所以你只需要一个额外的{{1}}作为临时的。好多了。