Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 正确编写循环、正循环和逆循环、C++;基础知识_C++_For Loop - Fatal编程技术网

C++ 正确编写循环、正循环和逆循环、C++;基础知识

C++ 正确编写循环、正循环和逆循环、C++;基础知识,c++,for-loop,C++,For Loop,因为循环很简单,对吗?嗯,我想知道一些事情,可能是因为我是一个物理学者,还没有受过适当的编程教育。 让我们以一个单词字符串为例,分别打印字符,然后按相反顺序打印 Q1)我们应该为大小声明一个变量并分配它并使用它,还是在for循环中调用字符串的size()函数 string s = "asdf"; int size = s.size(); for (int i = 0; i<size; i++){ cout<<s[i]<<endl; } string s=“as

因为循环很简单,对吗?嗯,我想知道一些事情,可能是因为我是一个物理学者,还没有受过适当的编程教育。 让我们以一个单词字符串为例,分别打印字符,然后按相反顺序打印

Q1)我们应该为大小声明一个变量并分配它并使用它,还是在for循环中调用字符串的size()函数

string s = "asdf";
int size = s.size();

for (int i = 0; i<size; i++){
 cout<<s[i]<<endl;
}
string s=“asdf”;
int size=s.size();

对于(int i=0;i您的问题的一般答案:您太担心了。好的编译器有优化器,可以创造奇迹。例如,一旦我用单独的变量替换了所有
i
,它实际上降低了我的程序速度

第二:为什么不简单地运行这些版本10^6次并测量它们呢?性能问题没有简单的答案

第三:一般规则是:以可读性最高的方式编写代码。例如,我将用以下方式实现反向循环:

for (int i = static_cast<int>(str.size()) - 1; i >= 0; i--)
    std::cout << str[i] << endl;
for(int i=static_cast(str.size())-1;i>=0;i--)

std::cout显而易见的答案是您应该使用迭代器:-):

对于反向迭代,我将使用:

int i = s.size();
while ( i != 0 ) {
    -- i;
    //  ...
}
(当然,如果要迭代多个容器 同时,您将先前提取尺寸,以 验证它们是否相等。然后使用提取的大小,
首先,您肯定希望养成在编译器中启用所有警告和调试信息的好习惯,而不是再次调用
s.size()。如果使用,请使用
g++-Wall-Wextra-g
编译。改进您的代码,直到您没有收到来自编译器的警告

您还希望您的代码具有可读性(或者是一些同事编写您的源代码,或者是您自己在几个月后尝试改进您的程序)。您可能希望您的代码是高效的

Q1)我们应该为大小声明一个变量并分配它并使用它吗

换句话说,就是

string s = "asdf";
int size = s.size();
for (int i = 0; i<size; i++){
   cout<<s[i]<<endl;
}

C++11的类型推断使您能够要求编译器猜测(自动C:s)的
C
和code
的类型,正如Spook所说,您太担心了:)

在C++11中,您可以对Q1执行类似的操作:

std::string myString("foo");
for (char c : myString)
{
    // TODO:
}

对于反向迭代,如果您想使用与上面相同类型的代码,那么首先必须像
std::reverse(myString.begin(),myString.end())那样进行反向迭代首先,您应该使用类中定义的类型。否则,程序的行为可能是不可预测的

所以不是

string s = "asdf";
int size = s.size();

for (int i = 0; i<size; i++){
 cout<<s[i]<<endl;
}

只有当size==0时,用户才会感到困惑,并且在一般情况下,如果条件将被更改,则可能会产生不可预测的结果,例如i!=0另一方面,int类型的对象不能容纳std::string::size\u类型的所有值

我通常使用这两种变体:

for(size_t i = 0, count = s.size(); i < count; i++) {...}
for(size_t i = s.size(); i--;) {...}

这很容易出现错误,因为它要求程序员/维护人员记住索引在整个循环体中都是一次性的。

我认为这并不重要,特别是在优化方面。这只是个人喜好。我认为Q2的B是一个不好的变体,因为你在写一个简单的例子时设法在那里创建了一个bug。是的,你是对的,它>0,这就是我为什么要问的!!(或其他)。使用
std::copy(s.begin()、s.end()、std::ostream\u迭代器(std::cout))
(或rbegin和rend)可以更好地处理您的所有示例。谢谢,您的答案非常有用!你愿意那样做吗?如果您必须打印一个反向,一个直接。@stefan,
i
的初始值将是
-1
,因此代码将正常工作。但这一点为何如此显而易见。而且也不能保证;在这种情况下,
i
的实际初始值由实现定义。(我从来没有听说过一个实现不是
-1
,但C标准甚至明确表示它可能会产生一个信号。)@JamesKanze为什么要定义实现?在求值-运算符时,可能会选择无符号整数而不是整数?我将代码更改为使用static_cast来解决此潜在问题。@Spook,因为
str.size()-1
的结果几乎肯定是一个超出
int
范围的无符号整数,并且这种转换的结果由实现定义。(这不是
无符号整数
的潜在选择;除非
大小_t
小于
整数
,否则这是标准要求的。)@JamesKanze现在应该可以正常工作了。顺便说一句,在这里使用无符号类型是一个奇怪的决定。它似乎带来的问题多于实际的好处(实际上,你不太可能希望在一个向量中保留超过2G的元素),我认为你可能对编译器优化器的工作持乐观态度。在许多实现中,
size()
将返回两个指针之间的差异。在许多情况下,编译器无法证明这两个指针在循环中没有被修改。(在像这个简单循环这样的情况下,它应该能够证明这一点,但很多编译器都没有足够的努力。)使用循环中任何地方都没有使用的局部变量来优化比较更简单,而不是在比较中使用。@JamesKanze,当我在程序中将
size()
更改为局部变量时(Visual Studio编译器),它实际上已经慢了下来。我学会了信任优化器,它们可以在编译代码中创造奇迹。使用任何非内联函数都是编译器的内存障碍,因此我认为编译器不会优化
vector.size() .@ MuleMyGeRoSurkCype记住,在C++标准中对 STD类有要求。可能(并且大多数是可能的)存在一些独立于实现的要求,这允许编译器优化siz()。
std::for_each(test.rbegin(), test.rend(), [=](char c) { std::cout << c << std::endl; });
for ( auto current = s.cbegin(), end = s.cend(); current != end; ++ current ) {
    std::cout << *current << std::endl;
}
for ( int i = 0; i != s.size(); ++ i )...
int i = s.size();
while ( i != 0 ) {
    -- i;
    //  ...
}
string s = "asdf";
int size = s.size();
for (int i = 0; i<size; i++){
   cout<<s[i]<<endl;
}
for (int i = 0; i<s.size(); i++){
   cout<<s[i]<<endl;
}
for (char c : s) 
   cout << c;
std::string myString("foo");
for (char c : myString)
{
    // TODO:
}
string s = "asdf";
int size = s.size();

for (int i = 0; i<size; i++){
 cout<<s[i]<<endl;
}
string s = "asdf";
string::size_type n = s.size();

for ( string::size_type i = 0; i < n; i++ ){
 cout << s[i] < <endl;
}
string s = "asdf";
string::size_type n = s.size();

for ( string::size_type i = 0; i < n; i++ ){
 cout << s[i] < <endl;
}
string s = "asdf";

for ( string::size_type i = 0, n = s,size(); i < n; i++ ){
 cout << s[i] < <endl;
}
for ( string::size_type i = 0; i < s.size(); i++ ){
 cout << s[i] < <endl;
}
for ( string::size_type i = s.size(); i != 0; i-- ){
 cout << s[i - 1] << endl;
}
for ( string::size_type i = s.size(); i != 0;  ){
 cout << s[--i] << endl;
}
for (int i = size - 1; i>= 0; i--){
for(size_t i = 0, count = s.size(); i < count; i++) {...}
for(size_t i = s.size(); i--;) {...}
for(size_t i = s.size(); i > 0; i--) {
    cout<<s[i - 1]<<endl;
}