2009-04-07 4 views
3

я был дан заголовок со следующим заявлением:Как мне изменить эту декларацию?

//The index of 1 is used to make sure this is an array. 
MyObject objs[1]; 

Однако, мне нужно, чтобы сделать этот массив динамически размера один запускается программа. Я бы подумал, что я должен просто объявить его как MyObject * objs ;, но я полагаю, что оригинальный программист объявил это таким образом, для этого есть некоторые причины.

Есть ли в любом случае я могу динамически изменять размер? Или я должен просто изменить его на указатель, а затем malloc()?

Могу ли я использовать какое-то новое ключевое слово для этого?

ответ

6

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

(Так как вы используете C++, почему не использовать оператор в нового вместо таНоса?)

MyObject* objs = new MyObject[size]; 
+0

должно быть, MyObject * objs = new MyObject [size]; правильно? – Tjofras

+0

О, я думаю, ты прав. Я так привык к C#, что заразил мой C++ :) –

16

Используйте STL vector:

#include <vector> 

std::vector<MyObject> objs(size); 

Вектор является dynamic array и является частью Standard Template Library. Он автоматически изменяет размер, как вы push back объектов в массив и может быть доступен, как обычный массив C с [] operator. Кроме того, &objs[0] гарантированно укажет на непрерывную последовательность в памяти - в отличие от list - если контейнер не пуст.

+0

"& objs [0] обязательно укажет на непрерывную последовательность в памяти". Но, пожалуйста, будьте осторожны: это нормально, когда вы уверены, что ваш вектор не пуст (например, с помощью метода empty()). В противном случае это может привести к неопределенному поведению. –

+0

Это верно и отмечено. –

+0

Если вы знаете размер заранее, тогда Vector :: reserve() будет вам полезна. –

0

Использование STL лучше всего, если вы хотите динамический размерный массив, существует несколько вариантов, один из которых - std::vector. Если вы не беспокоитесь о вставке, вы также можете использовать std :: list.

+0

Это не решает его проблему. Если он может изменить его на указатель, у него есть много возможностей для его изменения. realloc не позволит ему изменять размер массива при использовании текущего объявления. – jalf

0

Ее, кажется - да, вы можете сделать это изменение.
Но проверьте свой код на sizeof (objs);

MyObj *arr1 = new MyObj[1]; 
MyObj arr2[1]; 

sizeof(arr1) != sizeof(arr2) 

Возможно, этот факт используется где-то в вашем коде.

3

Или я должен просто изменить его на указатель , а затем malloc()?

Если вы это сделаете, как будут вызваны конструкторы для объектов в памяти malloc'd? Я дам вам подсказку - их не будет - вам нужно использовать std :: vector.

0

Этот комментарий невероятно плох. Одноэлементный массив представляет собой массив, хотя в комментарии предлагается иное.

Я никогда не видел, чтобы кто-нибудь пытался обеспечить «массив» таким образом. Синтаксис массива в основном является синтаксическим сахаром (a[2] дает тот же результат, что и 2[a]: т. Е. Третий элемент в a (ПРИМЕЧАНИЕthis is an interesting and valid syntax but usually a very bad form to use, потому что вы будете путать программистов без причины)).

Поскольку синтаксис массива является в значительной степени синтаксическим сахаром, переключается на указатель.Но если вы это сделаете, то с new[] будет больше смысла (потому что вы получите бесплатно свои конструкторы), а с std::vector имеет еще больше смысла (потому что вам не нужно забывать звонить delete[] каждое место массив выходит за пределы области из-за возврата, разрыва, завершения инструкции, исключения исключения и т. д.).

1

Я видел только массив, используемый как указатель внутри структуры или объединения. Это было давным-давно и использовалось для обработки len и первого символа строки как хеша, чтобы улучшить скорость сравнения строк для языка сценариев.

код был похож на это:

union small_string { 
    struct { 
     char len; 
     char buff[1]; 
    }; 
    short hash; 
}; 

Затем small_string был инициализирован с помощью таНос, обратите внимание, что с бросок эффективно reinterpret_cast

small_string str = (small_string) malloc(len + 1); 
strcpy(str.buff, val); 

И для проверки равенства

int fast_str_equal(small_string str1, small_string str2) 
{ 
    if (str1.hash == str2.hash) 
     return strcmp(str1.buff, str2.buff) == 0; 
    return 0; 
} 

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

Я бы, вероятно, избегал этого стиля C++ сегодня.

1

Это где-то в конце структуры?

Один трюк, который я видел, чтобы объявить STRUCT

struct foo { 
/* optional stuff here */ 
int arr[1]; 
} 

и таНос больше памяти, чем sizeof (struct foo) так, что arr становится переменной размера массива.

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

Правильная вещь, практически во всех случаях, состоит в том, чтобы изменить массив на вектор STL.