Подтвердить что ты не робот

Правильный путь цикла через массивы С++

Недавно я нашел много примеров, большинство из которых касается С++ 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

Он работает нормально, за исключением ошибки сегментации в конце.

Мой вопрос: действительно ли этот массив/цикл прошел хорошо? Я использую С++ 11, поэтому хотел бы убедиться, что он соответствует стандартам и не может быть сделан лучше?

4b9b3361

Ответ 1

В C/С++ sizeof. всегда задает количество байтов всего объекта, а массивы рассматриваются как один объект. Примечание: sizeof указатель - к первому элементу массива или одному объекту - указывает размер указателя, а не указатель на объект (ы). В любом случае sizeof не дает количество элементов в массиве (его длина). Чтобы получить длину, вам нужно разделить на размер каждого элемента. например.,

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

Что касается этого пути С++ 11, лучший способ сделать это, вероятно,

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

Это позволяет компилятору выяснить, сколько итераций вам нужно.

EDIT: как указывали другие, является предпочтительным в С++ 11 по сравнению с необработанными массивами; однако ни один из других ответов не объяснил, почему sizeof терпит неудачу, так что я все еще думаю, что это лучший ответ.

Ответ 2

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

Неа. Совершенно неправильный способ итерации через массив. sizeof(texts) не равно количеству элементов в массиве!

Современные, С++ 11 способов:

  • используйте std::array, если вам нужен массив, размер которого известен во время компиляции; или
  • используйте std::vector, если его размер зависит от времени выполнения

Затем используйте range-for при итерации.

#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;
    }
}

Живой пример


Вы можете спросить, как std::array лучше, чем массив ol 'C? Ответ заключается в том, что он обладает дополнительной безопасностью и особенностями других стандартных библиотечных контейнеров, в основном похожих на std::vector. Кроме того, ответ заключается в том, что он не имеет причуд распадающихся указателей и, таким образом, теряет информацию о типе, которая после того, как вы потеряете исходный тип массива, вы не можете использовать range-for или std::begin/end на нем.

Ответ 3

sizeof указывает размер элемента, а не количество элементов в нем. Более С++ 11 способ делать то, что вы делаете, будет следующим:

#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

Ответ 4

sizeof(texts) в моей системе оценивается до 96: количество байтов, необходимых для массива и его экземпляры строки.

Как уже упоминалось в другом месте, sizeof(texts)/sizeof(texts[0]) даст значение 3, которое вы ожидали.

Ответ 5

Добавить значение остановки в массив:

#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;
}