循环遍历 C++ 数组的正确方法

最近我发现了很多例子,其中大部分都是关于 C++ 98 的,反正我已经创建了我的简单数组和一个循环( codepad ):

#include <iostream>
using namespace std;

int main ()
{
   string texts[] = {"Apple", "Banana", "Orange"};
   for( unsigned int a = 0; a < sizeof(texts); a = a + 1 )
   {
       cout << "value of a: " << texts[a] << endl;
   }

   return 0;
}

输出:

value of a: Apple
value of a: Banana
value of a: Orange

Segmentation fault

它工作正常,除了最后的分段错误。

我的问题是,这个数组/循环是否做得很好?我正在使用 C++ 11,所以想确保它符合标准并且不能做得更好?

stack overflow more modern way of looping through C++ arrays
原文答案
author avatar

接受的答案

在C/C ++ sizeof 中。始终给出整个对象中的字节数,并且数组被视为一个对象。注意: sizeof 一个指针 - 对数组或单个对象的第一个元素 - 示出 pointer 的大小,而不是指向的对象。无论哪种方式, sizeof die not 给出数组中的元素数(其长度)。为了获得长度,您需要除以每个元素的大小。例如。,

for( unsigned int a = 0; a < sizeof(texts)/sizeof(texts[0]); a = a + 1 )

至于C ++ 11方法,最好的方法可能是

for(const string &text : texts)
    cout << "value of text: " << text << endl;

这使编译器可以弄清楚您需要多少迭代。

正如其他人指出的那样, std::array 在C ++ 11中优先于RAW数组。但是,没有其他答案解决了为什么 sizeof 失败的原因,所以我仍然认为这是更好的答案。


答案:

作者头像
string texts[] = {"Apple", "Banana", "Orange"};
for( unsigned int a = 0; a < sizeof(texts); a = a + 1 )
{
    cout << "value of a: " << texts[a] << endl;
}

Nope. Totally a wrong way of iterating through an array. sizeof(texts) is not equal to the number of elements in the array!

The modern, C++11 ways would be to:

  • use std::array if you want an array whose size is known at compile-time; or
  • use std::vector if its size depends on runtime

Then use range-for when iterating.

#include <iostream>
#include <array>


int main() {
    std::array<std::string, 3> texts = {"Apple", "Banana", "Orange"};
    // ^ An array of 3 elements with the type std::string

    for(const auto& text : texts) {   // Range-for!
        std::cout << text << std::endl;
    }
}

Live example


You may ask, how is std::array better than the ol' C array? The answer is that it has the additional safety and features of other standard library containers, mostly closely resembling std::vector. Further, The answer is that it doesn't have the quirks of decaying to pointers and thus losing type information, which, once you lose the original array type, you can't use range-for or std::begin/end on it.

作者头像

sizeof tells you the size of a thing, not the number of elements in it. A more C++11 way to do what you are doing would be:

#include <array>
#include <string>
#include <iostream>

int main()
{
    std::array<std::string, 3> texts { "Apple", "Banana", "Orange" };
    for (auto& text : texts) {
        std::cout << text << '\n';
    }
    return 0;
}

ideone demo: http://ideone.com/6xmSrn

作者头像

Add a stopping value to the array:

#include <iostream>
using namespace std;

int main ()
{
   string texts[] = {"Apple", "Banana", "Orange", ""};
   for( unsigned int a = 0; texts[a].length(); a = a + 1 )
   {
       cout << "value of a: " << texts[a] << endl;
   }

   return 0;
}
作者头像

you need to understand difference between std::array::size and sizeof() operator. if you want loop to array elements in conventional way then you could use std::array::size. this will return number of elements in array but if you keen to use C++11 then prefer below code

for(const string &text : texts)
    cout << "value of text: " << text << endl;
作者头像

If you have a very short list of elements you would like to handle, you could use the std::initializer_list introduced in C++11 together with auto:

#include <iostream>

int main(int, char*[])
{
    for(const auto& ext : { ".slice", ".socket", ".service", ".target" })
        std::cout << "Handling *" << ext << " systemd files" << std::endl;

    return 0;
}
作者头像

sizeof(texts) on my system evaluated to 96: the number of bytes required for the array and its string instances.

As mentioned elsewhere, the sizeof(texts)/sizeof(texts[0]) would give the value of 3 you were expecting.

作者头像

How about:

#include <iostream>
#include <array>
#include <algorithm>

int main ()
{
    std::array<std::string, 3> text = {"Apple", "Banana", "Orange"};
    std::for_each(text.begin(), text.end(), [](std::string &string){ std::cout << string << "\n"; });

    return 0;
}

Compiles and works with C++ 11 and has no 'raw' looping :)

作者头像

You can do it as follow:

#include < iostream >

using namespace std;

int main () {

   string texts[] = {"Apple", "Banana", "Orange"};

   for( unsigned int a = 0; a < sizeof(texts) / 32; a++ ) { // 32 is the size of string data type

       cout << "value of a: " << texts[a] << endl;

   }


   return 0;

}
作者头像

感觉像是非法的,但这有效:

所以基本上它是动态多维数组迭代终止情况,它与一维解决方案有点不同,最后一个元素是-1,它是循环的停止值(我是 C++ 新手,但我喜欢这种方法)

int arr[][3] = {{164, 0, 0}, {124, 0, 0}, {92, 4, 0}, {68, 4, 0}, -1};

for(int i = 0; arr[i][0]!=-1; i++)
{
    cout << i << "n";
}