我正在尝试使用基于for循环的新C ++ 11范围。这是我的计划:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
using namespace std;
ofstream logger("log.txt");
void log(string message)
{
logger << message << std::endl;
logger.flush();
}
int main( int argc, char* args[] )
{
log("hello world");
cout << "hello world\n";
log("declare sort me");
int sortMe[10];
log("loop sortMe");
for(int i : sortMe) {
log("in loop " + i);
sortMe[i] = i + 1;
}
}
我使用clang ++进行编译。它汇编了警告:
clang++ -o mycpp mycpp.cpp
mycpp.cpp:24:12: warning: range-based for loop is a C++11 extension
[-Wc++11-extensions]
for(int i : sortMe) {
^
1 warning generated.
当它运行时,我得到这个输出:
hello world
Segmentation fault (core dumped)
根据log.txt文件,程序进入for循环,但它永远不会进入for循环。我错过了什么?
答案 0 :(得分:10)
这个循环:
for(int i : sortMe) {
log("in loop " + i);
sortMe[i] = i + 1;
}
循环并返回sortMe
数组中存储的值,而不是sortMe
数组的 indices 。结果,查找sortMe[i]
将跳转到数组的完全随机索引(可能是方式,超出范围),导致段错误。
如果要将每个元素设置为等于其位置,只需使用普通for循环:
for (int i = 0; i < 10; i++) {
sortMe[i] = i + 1;
}
另外,正如@hmjd所指出的,对log
的调用将无法正常工作,因为您正在对字符串进行指针运算,而不是进行字符串连接。
希望这有帮助!
答案 1 :(得分:5)
您正在使用基于范围的for
循环,您应该使用标准for
循环。循环中的int i
不是当前元素的索引,而是该元素的值。也就是说,如果您的数组包含{1, 3, 3, 7}
,则每次迭代时i
的值为1
,然后为3
,然后为3
,然后为{{1} }}。由于您的数组未初始化,因此您不知道7
的值是什么,并且您将获得未定义的行为。
如果您想在for循环中使用索引,请使用标准for循环:
i
请注意,要与for(int i = 0; i < 10; i++) {
log("in loop " + std::to_string(i));
sortMe[i] = i + 1;
}
进行字符串连接,您的一个操作数需要为+
。否则,您将std::string
添加到指向i
中第一个字符的指针。
答案 2 :(得分:3)
for循环中对log()的调用不正确。参数是指针运算的结果,未知的int值用作字符串文字基址的偏移量。
使用std :: to_string()将int转换为std :: string。
提到std:iota,可用于将范围的元素设置为基于初始值的增加值:
std::iota(std::begin(sortMe), std::end(sortMe), 1);
答案 3 :(得分:1)
我认为您希望基于范围的循环可以做与其不同的操作......
如果你写for (int var: array) { log(var); }
那么代码将被执行的次数与数组中的元素一样多。每次var
都等于数组的一个元素。请注意,我直接使用var
作为数组元素,而不是array[var]
!
例如,如果你有int[3] array = { 42, 69, 1337 };
,循环的先例将记录42,69和1336。
因此,如果我只做int[3] array;
,循环的先例将循环存储数组的内存中的三个随机整数...如果不是直接使用var
我是使用array[var]
它很可能会崩溃,因为var不是array
的有效索引。
<强>解决方案:强>
不要对数组元素和索引之间的区别感到困惑......
如果您想直接操作数组的元素:
for(int element : sortMe) {
/* Do something with the element */
}
如果要使用索引,请不要使用基于范围的循环:
for(int index = 0; index < 10; ++index) {
/* Do something with the index */
}
答案 4 :(得分:0)
请不要向上或向下投票。我只是添加了一个我通常会添加的评论来帮助问题的人,但是因为你无法格式化....
你可以按照你想要的方式做新的方式,但这是一个相当无意义的练习,最好用常规的循环来完成。范围循环返回值,而不是引用。至少在你使用它的方式。
int count = 0;
// Use a reference so we can update sortMe
for (int& i : sortMe) {
i = ++count;
}
看着它,它比正常的循环更紧凑,奇怪的是我更喜欢它。 ;)