2014-10-02 2 views
0

В настоящее время я изучаю C++. Исходя из Java, для меня очень странно.Почему это не работает: `int arr [size]`, но это делает `int * arr = new int [size]`?

В какой-то момент я попытался создать массив размера, который определяется во время выполнения, например, так:

int size = functionCall(argument); 
int array[size]; 

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

Кто-то сказал мне, что я должен сделать это:

int size = functionCall(argument); 
int* array = new int[size]; 

Поскольку new позволяет материал динамически распределять, то есть, если я правильно понял распределяется в соответствии с чем-то, что это только известным во время выполнения.

Два вопроса:

1- мое понимание new правильно?

2- Почему C++ не разрешает первую версию моего кода?

+0

Возможный дубликат [Как вы инициализируете динамический массив в C++?] (Http://stackoverflow.com/questions/2029651/how-do-you-initialise-a-dynamic-array-in-c) – dandan78

+0

Первое не работает, потому что ... ну, потому что синтаксис неверен. Синтаксис на разных языках различен, и используемый вами синтаксис недействителен C++. –

+0

@ DavidRodríguez-dribeas Конечно, но сказать 'int array [8]' * is * действительный синтаксис, не так ли? –

ответ

8

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

Вы создали нестандартное расширение под названием VLA (A.K.A. Variable-length Array). Это должно было сработать, правда, но поскольку я не предполагал, что с вашей стороны что-то пошло не так.

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

Да, ваша интуиция верна.

1- Мое понимание нового правильного?

Да. Для динамического выделения памяти используется new. Но это открывает еще одну банку червей.

2- Почему C++ не разрешает первую версию моего кода?

Стандарт C++ просто не поддерживает VLA. Я чувствую, что аргументация этого не выходит за рамки вопроса.

В любом случае, если вам нужен динамический массив на основе переменной времени выполнения на C++, мы склонны использовать std::vector. You код будет затем в конечном итоге это:

std::size_t size = get_size(); 
std::vector<int> arr(size); 

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

+0

Изменено название. Фраза 'int []' не является C++. –

1
int size = functionCall(argument); 
int* x = new int[size]; 

size не известно во время компиляции. это известно только во время выполнения. Поэтому вам нужно использовать heap allocation для вашего массива. Компилятор не знает, какой размер должен иметь этот массив во время компиляции, поэтому он должен попросить распределитель памяти кучи во время выполнения выделить достаточное пространство, когда он знает, что такое size. Ключевое слово new - это запрос памяти кучи.

если вы сделали

static const int size = <constexpression> 
int x[size]; 

, например, если constexpression был 3 (а size_t кабриолет буквальным) или что-то, что было известно во время компиляции, то он будет использовать stack allocation, так как компилятор будет знать во время компиляции хау большой массив должен быть, и вам будет разрешено это сделать.

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

std::vector<int> x(size); 

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

std::array<int, size> x; // where size is known at compile time 
+0

downvoters, пожалуйста, объясните, как можно улучшить ответ или что не так. –

+1

Я дал ответ, очень похожий на ваш, и он также был опущен. Я, наконец, удалил его: я должен что-то упустить ... –

+0

Что-то, что вам не хватает, это 'std :: vector'. –

0

C++ получается в основном из C (а не из Java), поэтому мы находим несколько вещей на C++, которые можно найти также в C, например, распределение динамической памяти. В C++ вы можете создавать объекты на heap, с new, или на stack, без new.В Java, фактически, все не примитивные объекты, которые создаются с new, также выделяются в куче, но вам не нужно заботиться об удалении ранее выделенных объектов, потому что на Java есть сборщик мусора:

// In Java, with the following expression, 
// you are actually allocating an object of type `Type1` on the heap 
Type1 obj = new Type1(); 

в C++, если вы хотите создать объект в куче, вы должны также удалить распределенную память (в Java, у вас есть GC):

Type1* obj = new Type1(); 
// use the pointer obj 
delete obj; // deleting the object. 
2

C++ (в отличие от современного C) не позволяет инициализировать массив, используя значение, которое вычисляется во время выполнения. Можно сделать

int x[size]; 

в C++, но значение, содержащееся в size должно быть известно компилятором. Таким образом, следующее является законным

int const size = 10; // Known at compile-time 
int x[size]; 

Но следующий не

int size; 
cin >> size; // we only know size at run-time 
int x[size]; // ERROR! 

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

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

std::vector<int> xs(10); // allocate space for ten ints. 

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

Итак, в заключение:

  1. Да, ваше понимание new правильно. Если вы знаете только размер во время выполнения, вам нужна динамическая память. Однако избегайте использования new, если это вообще возможно: предпочитайте vector.
  2. C++ просто не позволяет массивам иметь размеры, известные во время выполнения. Все массивы, созданные в стеке, должны быть известны во время компиляции. Это отличается от C, если такая вещь разрешена.
Смежные вопросы