2017-02-16 6 views
3

В C++ я чувствую себя очень неудобно, что C++ не имеет встроенной функции для динамического выделения памяти для многомерных массивов во время выполнения.Почему у C++ нет удобного способа динамического выделения памяти для многомерного массива?

В Java мы можем просто сделать одну строку кода. Например, в Java, мы можем динамически выделять память для 4D целочисленного массива с

int a, b, c, d; 
std::cin>>a>>b>>c>>d; 
int[ ][ ][ ][ ] array = new int[a][b][c][d]; 

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

+3

Интересный забавный факт: этот массив 4D в Java? Это не 4D-массив. Это массив массивов массивов массивов целых чисел.Это может быть болезненно медленным, потому что между каждым динамически выделенным вспомогательным массивом нет связи. CPU отскакивает от одного распределения к другому и никогда не справляется с тем, чтобы получить скорость, которую он может получить из непрерывных данных, все предварительно загруженные в кеш. Ужасное вложенное решение C++ цикла делает то же самое, и это ужасно. Если вам не нужны зубчатые массивы, не делайте этого ни на одном из языков. Создайте оболочку вокруг массива 1D, который обрабатывает индексирование для вас. – user4581301

+0

Вот пример: https://isocpp.org/wiki/faq/operator-overloading#matrix-subscript-op – user4581301

ответ

9

В C++ вы также можете выделить память таким образом. Например :)

auto array = new int[3][4][5][6]; 

или что является тем же самым

int (*array)[4][5][6] = new int[3][4][5][6]; 

Или вы можете использовать ЬурейеЕ как

typedef int T[4][5][6]; 
// or 
// using T = int[4][5][6]; 

T *array = new T[3]; 

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

+0

Другая проблема заключается в том, что у нее есть тенденция утечки памяти, когда вы, например, выходите необычным способом – sp2danny

+0

Благодаря! Я забыл, что мы можем использовать авто. Таким образом, тип авто будет таким же, как int * array [] [] []? Ваш ответ действительно полезен! Но есть ли способ сделать это, используя непостоянные выражения во время выполнения? В большинстве случаев мне не нужно использовать многомерные массивы. Но я решил хорошо изучить C++ и хочу узнать больше об этом. Таким образом, мой второй вопрос заключается в том, какой контекст подходит для использования многомерных массивов? Всегда ли мы должны их избегать? –

+0

@HanM Смотрите мой обновленный пост. Я показал альтернативные заявления. К сожалению, выражения должны быть постоянными. Поэтому вместо массивов, когда количество элементов неизвестно во время компиляции, обычно используются стандартные контейнеры, такие как std :: vector в C++. –

1

Мы также можем создать 2D прямоугольного массив размера (M, N) в качестве

auto array = (int (*)[N]) new int [ M*N ]; 

и 3D массив размера (L, M, N) в качестве

auto array = (int (*)[M][N]) new int [ L*M*N ]; 

и т.д. (где L, M, N, ... могут быть переменными). Определение макроса для этого может быть удобным. Кроме того, если размер мал, мы не можем просто сделать, как

int array[M][N]; 

(я узнал об этом раньше от Stackoverflow, спасибо большое!)

+0

«int array [M] [N]» не беспокоится об утечке, потому что он выделен в стеке (правильно?), Но использование «новых» и указателей имеет риск утечки; поэтому я думаю, что практически лучше (безопаснее) использовать какой-либо существующий контейнерный класс или быстрые библиотеки для многотоновых массивов, особенно для численных расчетов. – roygvib

+0

Спасибо! Я новичок в C++ и не уверен, что такое значения (int (*) [N]) и (int (*) [M] [N]). Они кажутся типами. Но я не уверен, как правильно их понять. Они также кажутся родовыми выражениями. –

+0

@ HanM Привет, это совсем не особая вещь, это просто литье типов к указателю на прямоугольный массив (см. Также второй пример Влада). Если вы найдете несколько лучших способов для многотоновых массивов, пожалуйста, дайте мне знать также :) – roygvib

2

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

Шаг нулю, собственно включает в себя

#include <gsl/multi_span> 
#include <memory> 

Шаг один, установленные размеры

constexpr int x_sz = 3; 
constexpr int y_sz = 4; 
constexpr int z_sz = 5; 
constexpr int total = x_sz * y_sz * z_sz; 

Шаг два, выделение памяти

auto arrptr = std::make_unique<int[]>(total); 

Шаг три, создать вид массива

gsl::multi_span<int, x_sz, y_sz, z_sz> arr3d { arrptr.get(), total }; 

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

Вы можете найти GSL here

+0

Спасибо! Является ли GSL еще не законченным? Я планирую прочитать это, когда он будет закончен. –