C++ for(char&;c:s)和for(char c:s)之间的区别是什么?
这是leetcode上的一个问题 给定一个只包含字符“(”、“)”、“{”、“}”、“[”和“]”的字符串,确定输入字符串是否有效 括号必须按正确的顺序闭合,“()”和“()[{}”都有效,但“(]”和“([)]”无效 这是一个解决方案:C++ for(char&;c:s)和for(char c:s)之间的区别是什么?,c++,C++,这是leetcode上的一个问题 给定一个只包含字符“(”、“)”、“{”、“}”、“[”和“]”的字符串,确定输入字符串是否有效 括号必须按正确的顺序闭合,“()”和“()[{}”都有效,但“(]”和“([)]”无效 这是一个解决方案: class Solution { public: bool isValid(string s) { stack<char> paren; for (char& c : s) {
class Solution {
public:
bool isValid(string s) {
stack<char> paren;
for (char& c : s) {
switch (c) {
case '(':
case '{':
case '[': paren.push(c); break;
case ')': if (paren.empty() || paren.top()!='(') return false; else paren.pop(); break;
case '}': if (paren.empty() || paren.top()!='{') return false; else paren.pop(); break;
case ']': if (paren.empty() || paren.top()!='[') return false; else paren.pop(); break;
default: ; // pass
}
}
return paren.empty() ;
}
};
class Solution {
public:
bool isValid(string s) {
stack<char> paren;
for (char c : s) {
switch (c) {
case '(':
case '{':
case '[': paren.push(c); break;
case ')': if (paren.empty() || paren.top()!='(') return false; else paren.pop(); break;
case '}': if (paren.empty() || paren.top()!='{') return false; else paren.pop(); break;
case ']': if (paren.empty() || paren.top()!='[') return false; else paren.pop(); break;
default: ; // pass
}
}
return paren.empty() ;
}
};
在第一个解决方案中
for (char c : s)
在第二种解决方案中。
然而,第一种解决方案只需要3毫秒,第二种解决方案需要6毫秒。
那么为什么第一种解决方案比第二种解决方案快呢
for (char c : s)
这将在s
中创建每个元素的副本,并将其存储在c
中。这意味着修改c
不会修改s
for (char& c : s)
这不会在s
中创建每个元素的副本,而是直接引用并将其作为别名存储在c
中。这意味着修改c
会修改s
for (char& c : s)
由于复制可能是一项昂贵的操作,因此它的性能比引用慢(即使在不存在优化的情况下使用内置类型),从而避免了复制 如果要防止无意中修改字符串,则可以使用
const
引用,即:
for (const char& c : s)
记得启用优化吗?一个类似于函数的参数
void foo(char&);
,另一个类似于foo(char);
可能通过常量引用获取函数参数(即bool isValid(string const&s)
)因此,避免复制会给您带来更多的加速。另一个加速的方法是为堆栈保留内存(与输入字符串的内存相同),避免在push()
中重新分配。您可能会认为任何级别的优化都应该避免复制这个简单的代码,还是不?“与参考相比,它的性能更慢",这并不总是正确的,尤其是对于内置类型。谢谢!我对编码是新手,我发现我有很多东西要学!@songyuanyao,这可能很大程度上取决于优化水平,不是吗?@Walter是的,当然,在进行性能测量之前。但是作为我从有效的C++是“”。