Вычислительная длина массива - PullRequest
5 голосов
/ 14 июля 2009

У меня есть массив C ++, объявленный как указано ниже:

CString carray[] =
{
        "A",
        "B",
        "C",
        "D",
        "E"
}

Я хочу определить длину carray во время выполнения. Я делаю:

int iLength = sizeof(carray)/sizeof(CString);

Это правильно?

Ответы [ 10 ]

24 голосов
/ 14 июля 2009

Вы можете использовать следующий шаблон функции. Если вы используете Boost, вы можете позвонить boost::size.

template <typename T, std::size_t N>
std::size_t size(T (&)[N])
{
    return N;
}

int iLength = size(carray);

Как уже говорили другие, вы должны предпочесть std::vector массивам в стиле C.

17 голосов
/ 14 июля 2009

Да. Если объявленный тип элемента когда-либо изменится, вы также можете написать

int iLength = sizeof(carray)/sizeof(carray[0]);
6 голосов
/ 14 июля 2009

Это правильно, так как он использует метапрограммирование как это:

template <typename T, std::size_t N>
inline std::size_t array_size( T (&)[N] ) {
   return N;
};

Вы должны знать, что это работает, когда компилятор видит определение массива, но не после того, как он был передан функции (где он распадается в указатель):

void f( int array[] )
{
   //std::cout << array_size( array ) << std::endl; // fails, at this point array is a pointer
   std::cout << sizeof(array)/sizeof(array[0]) << std::endl; // fails: sizeof(int*)/sizeof(int)
}
int main()
{
   int array[] = { 1, 2, 3, 4, 5 };
   f( array );
   std::cout << array_size( array ) << std::endl; // 5
   std::cout << sizeof(array)/sizeof(array[0]) << std::endl; // 5 
}
5 голосов
/ 14 июля 2009

Этот код верен, но в большинстве случаев есть лучшие способы обработки массивов в C ++. Тем более что этот метод не будет работать с массивами динамического размера.

Для таких случаев используйте стандартный библиотечный класс std::vector, представляющий массив динамического размера (т.е. вы можете вставлять и удалять записи).

1 голос
/ 14 июля 2009

Да, это правильный способ сделать это, но он будет работать только в той ситуации, когда размер массива известен во время компиляции и виден на сайте оператора sizeof( array ). Он не будет работать с массивами динамического размера - вам понадобятся другие методы для них, например, использование контейнера типа stl :: vector или передача / хранение количества элементов в качестве отдельного параметра.

0 голосов
/ 14 июля 2009

Лучший способ - использовать макрос и использовать его там, где вам нужен размер.

#define MAX_ROWS 1048
int array[MAX_ROWS];

Таким образом, вы можете использовать MAX_ROWS даже в функции, где массив передается в качестве аргумента.

0 голосов
/ 14 июля 2009

Windows SDK (т.е. заголовок windows.h) предлагает макрос ARRAYSIZE, который реализует эту функцию безопасным способом (т.е. не работает с нестатическими массивами)

0 голосов
/ 14 июля 2009

Читать это статья Иван Дж. Джонсон в Д-р. Доббс Журнал. Я думаю, что это покрывает большинство решений, представленных здесь. Он также очень хорошо описывает достоинства и недостатки каждого подхода.

0 голосов
/ 14 июля 2009

Если у вас есть динамический массив, вам, вероятно, следует использовать что-то вроде вектора STL. http://www.cppreference.com/wiki/stl/vector/start

Обычные массивы в C ++ имеют фиксированный размер, и вам нужно вручную выделять память для расширения динамических.

Если вы знаете размер вашего массива во время компиляции, используйте константу, а не расчет.

0 голосов
/ 14 июля 2009

Это не время выполнения, это время компиляции. То, как вы используете, является правильным. Обратите внимание, что Visual Studio определяет функцию _countof, которая делает то же самое.

Во время выполнения длина не может быть определена. Вы либо сами держите длину, либо используете std::vector

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...