Заполнение набора с массивами

Существует два места, куда переменные могут быть помещены в память. Когда Вы создаете переменную как это:

int  a;
char c;
char d[16];

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

Много примеров новичка будут использовать только переменные стека.

стек хорош, потому что это автоматически, но это также имеет два недостатка: (1) компилятор должен знать заранее, насколько большой переменные, и (b), стековое пространство несколько ограничено. Например: в Windows, при настройках по умолчанию для компоновщика Microsoft, стек установлен на 1 МБ, и не все это доступно для Ваших переменных.

, Если Вы не знаете во время компиляции, насколько большой Ваш массив, или если Вам нужны большой массив или структура, Вам нужен "план B".

План B называют" "куча" ". Можно обычно создавать переменные, столь большие, как Операционная система позволит Вам, но необходимо сделать это сами. Более ранние регистрации показали Вам один способ, которым можно сделать это, хотя существуют другие пути:

int size;
// ...
// Set size to some value, based on information available at run-time. Then:
// ...
char *p = (char *)malloc(size);

(Отмечают, что переменными в "куче" не управляют непосредственно, но через указатели)

, Как только Вы создаете переменную "кучи", проблема состоит в том, что компилятор не может сказать, когда Вы сделаны с ним, таким образом, Вы теряете автоматический выпуск. Это - то, где "руководство, выпускающее", Вы обращались к, входит. Ваш код теперь ответственен для решения, когда переменная больше не нужна, и выпустите его так, память может быть взята для других целей. Для случая выше, с:

free(p);

, Что делает эту вторую опцию, "противный бизнес" то, что не всегда легко знать, когда переменная больше не нужна. Упущение выпустить переменную, когда Вам не нужен он, заставит Вашу программу использовать больше памяти, что это должно. Эту ситуацию называют "утечкой". "Пропущенная" память не может использоваться ни для чего до Ваших концов программы, и ОС восстанавливает все свои ресурсы. Еще более противные проблемы возможны при выпуске переменной "кучи" по ошибке прежде , Вы на самом деле сделаны с нею.

В C и C++, Вы ответственны для чистки переменных "кучи" как показанный выше. Однако существуют языки и среды, такие как Java и языки.NET как C#, которые используют другой подход, где "куча" очищена самостоятельно. Этот второй метод, названный "сборкой"мусора"", намного легче на разработчике, но Вы платите штраф в издержках и производительности. Это - баланс.

(я замял много деталей для предоставления более простого, но надо надеяться более выровненный ответ)

11
задан Community 9 July 2018 в 19:34
поделиться

4 ответа

Хммм ... синтаксис выглядит достаточно легальным без VBA перед мне. Я прав в том, что ваша проблема в том, что ваш код «компилируется» и выполняется, не вызывая ошибки, но что массив в коллекции никогда не изменяется? Если так, я думаю, это потому, что ваш A.Item (1) может возвращать копию массива, который вы сохранили в коллекции. Затем вы получаете доступ к выбранному элементу и изменяете его, но это не дает желаемого эффекта, потому что это неправильный экземпляр массива.

В целом коллекции VBA работают лучше всего при хранении объектов. Тогда они будут работать так, как вы хотите, потому что в них хранятся ссылки. Они хороши для хранения значений, но я думаю, они всегда их копируют, даже "большие" такие как варианты массива, что означает, что вы не можете изменять содержимое хранимого массива.

Считайте этот ответ просто предположением, пока кто-то, кто лучше знает базовый материал COM, не взвесит. Эм ... пейджинг Джоэл Спольски?

РЕДАКТИРОВАТЬ: Я думаю, что, попробовав это в Excel VBA, прав. Включение варианта массива в коллекцию создает копию, равно как и ее получение. Таким образом, похоже, нет прямого способа кодировать то, о чем вы на самом деле просили.

Похоже, что на самом деле вам нужен трехмерный массив, но тот факт, что вы пытались использовать коллекцию для первого измерения, подразумевает, что вы хотите иметь возможность изменять его размер в этом измерении. VBA позволит вам изменить размер только последнего измерения массива (см. «Redim preserve» в справке). Вы можете поместить свои двумерные массивы в одномерный массив, размер которого вы можете изменить, однако:

ReDim a(5)
Dim b(2, 2)
a(2) = b
a(2)(1, 1) = 42
ReDim Preserve a(6)

Обратите внимание, что a объявляется с помощью ReDim, а не Dim в данном случае.

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

9
ответ дан 3 December 2019 в 07:13
поделиться

@jtolle верен. Если вы запустите приведенный ниже код и проверите значения (Quick Watch - Shift-F9) Arr2 и x, вы увидите, что они разные:

Dim A As Collection
Set A = New Collection
Dim Arr2(15, 5)

Arr2(1, 1) = 99

' ...

A.Add (Arr2) ' adds a copy of Arr2 to teh collection

Arr2(1, 1) = 11  ' this alters the value in Arr2, but not the copy in the collection

Dim x As Variant

x = A.Item(1)
x(1, 1) = 15  ' this does not alter Arr2
5
ответ дан 3 December 2019 в 07:13
поделиться

Возможно, VBA делает копию массива, когда он присваивает его коллекции? VB.net этого не делает. После этого кода (3,3) равно 20 в vba и 5 в vb.net.

Dim c As New Collection
Dim a(10, 10) As Integer

a(3, 3) = 20
c.Add(a)
c(1)(3, 3) = 5
2
ответ дан 3 December 2019 в 07:13
поделиться

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

1
ответ дан 3 December 2019 в 07:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: