2009-12-25 2 views
2

Я читал, чтобы получить длину массива в C++, вы делаете это:длина массива в C++

int arr[17]; 
int arrSize = sizeof(arr)/sizeof(int); 

Я попытался сделать то же самое для строки: где я

string * arr; 
arr = new (nothrow) string [213561]; 

а потом я

arr[k] = "stuff"; 

где цикл по каждому индексу и положить «материал» в нем.

Теперь я хочу размер массива, который должен быть 213561, что это правильный способ сделать это и почему он настолько сложный в C++?

+0

Это не «так сложно» - вы не можете делать то, что вы просите в C. – 2009-12-25 16:05:32

+0

У вас есть фон, в котором язык программирования? – Partial

+0

Я не понимаю, размер массива - это исходный номер, который вы использовали для его создания. Просто определите его как именованную константу и обратитесь к константе. Что касается знания количества элементов в массиве, вам придется отслеживать это. В противном случае используйте 'std :: vector'. –

ответ

6

Правильный способ сделать это на C++ - использовать vector. Таким образом, вы можете либо указать размер вверх, либо изменить его размер по мере продвижения.

Указание размера до фронта:

using namespace std; 
vector<string> arr(213561); 

for (vector<string>::iterator p = arr.begin(); p != arr.end(); ++p) 
{ 
    *p = "abc"; 
} 

расширяющейся вектор, как вы идете:

using namespace std; 
vector<string> arr; // <-- note, default constructor 

for (int i = 0; i < 213561; ++i) 
{ 
    // add elements to the end of the array, automatically reallocating memory if necessary 
    arr.push_back("abc"); 
} 

В любом случае, размер массива находится с:

size_t elements = arr.size(); // = 213561 
0

Вам нужно отслеживать длину, используя отдельную переменную. Нет способа получить длину области, к которой у вас есть только указатель, если вы не сохраните эту длину где-нибудь.

0

Вы не можете получить длину выделенного массива. Что вы можете сделать, это сохранить его отдельно во время выделения.

Кроме того, вы можете проверить длину строки (это не то, что вы просите, но все же ...), используя strlen()

8

То, что вы пытаетесь сделать, не может работать, потому что sizeof работает с типами во время компиляции (и типы указателей никогда не удерживают размер массива, на который они могут ссылаться).

В вашем случае вычисление SizeOf (обры) возвращают размер принятого в памяти по указателю, а не

size of the array * size of a std::string 

Я предлагаю вам использовать один из этих двух вариантов

  • либо использовать фиксированный размер массивов (SizeOf работы)
  • или векторы (myVector.size() возвращает то, что вам нужно)

... если у вас нет оснований не делать этого.

0

В C++ здесь arr - это просто ссылка на первый элемент массива. В случае динамических массивов это невозможно.

1

Метод sizeof работает только до тех пор, пока ваш массив действительно является массивом, то есть объектом, который имеет тип массива. В вашем первом примере объект arr имеет тип int[17]. Это тип массива, что означает, что вы можете использовать метод sizeof и получить 17.

После преобразования вашего типа массива T[N] в тип указателя T * вы в основном теряете свой тип массива. Метод sizeof, применяемый к указателю, не будет оценивать размер исходного массива.

Когда вы выделяете массив типа T[N] с new[], результатом является указатель типа T *. Это не тип массива с самого начала. Информация о размере массива сразу теряется, и попытка использования метода sizeof с таким указателем не будет работать. Чтобы сохранить информацию о размерах динамически распределенного массива времени выполнения, вам нужно сохранить его в отдельной переменной самостоятельно.

+0

Nitpick: sizeof - это оператор, а не метод. И sizeof не возвращает количество элементов в массиве, а размер в байтах (или, вернее, символы). –

+0

А? Я сам не называл 'sizeof'« методом ». «Метод sizeof», о котором я говорю, - это известный метод * определения * подсчета элементов в заданном массиве 'a' путем выполнения' sizeof a/sizeof * a'. Он называется «sizeof trick», «sizeof method» и многими другими именами. Пожалуйста, приучитесь к принятому языку или, по крайней мере, разработайте интуицию, прежде чем вы начнете голосовать за ответы людей. – AnT

+0

@ Andrey: Извините. Я совершенно неправильно читаю ваш пост. В моей защите я просто скажу, что довольно распространенное заблуждение, что sizeof является функцией, а поскольку «метод» имеет конкретное значение в объектно-ориентированном контексте, я неправильно понял, что вы написали. (Сдвиг слишком старый, чтобы его можно было изменить, поэтому я посмотрел на некоторые ваши ответы и поддержал их.) –

0

В C и C++ есть тонкий нюанс с распределением памяти. Ни один из языков не поддерживает динамические массивы. Вот то, что вы видите:

int ary[17]; 
int arrSize = sizeof(ary)/sizeof(ary[0]); 

Здесь ary настоящий массив из 17 целых чисел. Расчет размера массива работает, потому что sizeof(ary) возвращает размер блока памяти, выделенного для всего массива. Вы делите это по размеру каждого элемента и violà у вас есть количество элементов в массиве.

std::string * arr; 
arr = new (std::nothrow) std::string[213561]; 

В этом случае arr является указателем на какую-то память. Оператор new выделяет блок памяти, достаточно большой для хранения 213 561 смежных объектов std::string и создает каждый из них в памяти. Переменная arr просто указывает на начало блока памяти. C++ не отслеживает количество выделенных элементов. Вы действительно не создали динамический массив - вместо этого вы выделили достаточно памяти для связки смежных объектов.

C и C++ оба позволяют применять оператор подписи к указателю как синтаксический сахар. Вы увидите много комментариев о том, как arr[0] переводит *(arr + 0). Реальность заключается в том, что выделение памяти с использованием оператора new приводит к блоку памяти, который не является массивом вообще. Синтаксический сахар делает его похожим на одно. Следующее, что вы столкнетесь, это то, что многомерные массивы похожи на сахар.

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

#include <iostream> 

int 
main() 
{ 
    // 
    // The compiler translates array subscript notation into 
    // pointer arithmetic in simple cases so "hello"[3] is 
    // is translated into *("hello" + 3). Since addition is 
    // commutative, the order of "hello" and 3 are irrelevant. 
    // 
    std::cout 
     << "\"hello\"[3] = '" << "hello"[3] << "'\n" 
     << "3[\"hello\"] = " << 3["hello"] << "\n" 
     << std::endl; 

    // 
    // All memory is linear in C or C++. So an 3x3 array of 
    // integers is a contiguous block of 9 integers in row 
    // major order. The following snippet prints out the 3x3 
    // identity matrix using row and column syntax. 
    // 
    int ary[3][3] = { { 1, 0, 0 }, 
         { 0, 1, 0 }, 
         { 0, 0, 1 } }; 
    for (int r=0; r<3; ++r) { 
     for (int c=0; c<3; ++c) { 
      std::cout << "\t" << ary[r][c]; 
     } 
     std::cout << "\n"; 
    } 
    std::cout << "\n"; 

    // 
    // Since memory is linear, we can also access the same 
    // 3x3 array linearly through a pointer. The inner loop 
    // is what the compiler is doing when you access ary[r][c] 
    // above - "ary[r][c]" becomes "*(ptr + (r * 3) + c)" 
    // since the compiler knows the dimensions of "ary" at 
    // compile time. 
    // 
    int *ptr = &ary[0][0]; 
    for (int i=0; i<9; ++i) { 
     ptr[i] = i; 
    } 
    for (int r=0; r<3; ++r) { 
     for (int c=0; c<3; ++c) { 
      std::cout << "\t" << *(ptr + (r * 3) + c); 
     } 
     std::cout << "\n"; 
    } 

    return 0; 
} 
+0

Я не вижу, что этот код пытается выполнить? – SuperString

1

Вот как вы находите размер массива:

const size_t ARRAY_SIZE = 17; 
int array[ARRAY_SIZE]; 
//... 
std::cout << "My array size is: " << ARRAY_SIZE << "\n"; 

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

Если вам нужен динамический массив, который будет расти по мере необходимости, попробуйте std::vector.

Смежные вопросы