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

#c #arrays #pointers #dynamic

#c #массивы #указатели #динамический

Вопрос:

Например:

 int* pArray;
pArray = new array[];
  

вместо:

 int* pArray;
pArray = new array[someNumber];
  

Поскольку указатели могут динамически изменять размер массива во время выполнения, а имя указателя указывает на первый элемент массива, разве размер по умолчанию не должен быть [1] ? Кто-нибудь знает, что происходит за сценой?

Комментарии:

1. «Поскольку указатели способны динамически изменять размер массива во время выполнения …». Кто вам это сказал? Если вы услышали это от профессора, либо она ошиблась, либо вы ее ослышались. Если вы прочитали это в книге, сообщите нам название книги, чтобы мы могли рекомендовать ее не использовать.

2. @Rob Я, должно быть, неправильно понял своего профессора.

3. @TadeuszKopec: Я думаю, это неуместно. Многие вещи, которые мы считаем само собой разумеющимися, не очевидны для новичков, и это к счастью . Инновациями движут люди, пытающиеся освободиться от старых моделей, поэтому я бы не стал ругать людей за то, что они задают вопросы (даже когда ответ кажется очевидным), если вопросы (подобные этому) хорошо написаны.

Ответ №1:

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

Это неверно. Они не могут изменить размер, если вы не выделите новый массив с новым размером.

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

 #include<vector>
#include<iostream>

...
std::vector<int> array;

array.push_back(1);
array.push_back(2);
array.push_back(3);
array.push_back(4);

std::cout << array.size() << std::endl; // should be 4
  

Комментарии:

1. Спасибо, это был фундаментальный недостаток в моем мышлении.

Ответ №2:

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

Когда вы «изменяете размер» массива, вы создаете новый массив (с еще большим объемом памяти) и копируете элементы перед удалением старого массива (иначе у вас утечка памяти).

Ответ №3:

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

Комментарии:

1. Отличный ответ! Я знаю, что они не могут изменять свой размер автоматически, но я также знаю, что при создании массива выделяется память для хранения содержимого этого массива. Я не был уверен, существует ли размер по умолчанию, основанный на типе. Теперь я знаю, спасибо.

Ответ №4:

Указатели не могут изменять массив. Однако их можно заставить указывать на разные массивы во время выполнения.

Тем не менее, я предлагаю вам держаться подальше от всего, что связано new с этим, пока вы не узнаете больше о языке. Для динамического изменения размера массивов используйте std::vector .

Комментарии:

1. Если я буду держаться подальше от new, как я должен изучать язык? Я знаю, что такое объект и экземпляр (и, следовательно, я понимаю назначение new ), так когда бы вы предложили мне начать использовать new ? Кроме того, я предлагаю вам держаться подальше от комментариев к stack, пока вы не сможете придумать конструктивные комментарии, которые не перефразируют последние две публикации.

2. @Hollis Могу я предложить вам проявить больше уважения к людям, пытающимся вам помочь, потратив их время на ответы на ваши вопросы? Особенно, когда эти люди являются ценными членами сообщества, которые более чем доказали свои навыки на этом сайте.

3. @Hollis: Вы используете автоматические (основанные на стеке) объекты. Вы также можете использовать те, которые обертывают динамические (основанные на куче) объекты, как это делает std::vector or std::string . Не путаться с std::vector итераторами и их итераторами достаточно сложно для новичка. Когда я преподавал C , std::vector это было введено примерно в третьей лекции, new может быть, в десятой.

4. @Hollis: Что касается вашего предложения: пожалуйста, не будьте грубыми. Когда я писал свой ответ, никто еще не высказал тех соображений, которые я высказал. С тех пор более ранний ответ был изменен, чтобы включить его (и я поддержал его за это), но тогда этого не было.

5. @sbi Мы даже не рассмотрели векторы в моем классе. Мы уже перешли от указателей к связанным спискам, и он никогда не упоминал векторы. Я неправильно понял, что говорил мой профессор о возможности изменять размер массивов во время выполнения. Я вернулся к своим заметкам и, по сути, он говорил, что пользователь может указать размер и создать новый массив во время выполнения, а не изменять размер данного массива во время выполнения.

Ответ №5:

Указатели указывают на динамически выделяемую память. Память находится в куче, а не в стеке. Он динамический, потому что вы можете вызывать для него new и delete , добавляя к нему и удаляя из него во время выполнения (проще говоря). Указатель не имеет к этому никакого отношения — указатель может указывать на что угодно, и в этом случае он просто указывает на начало вашей динамической памяти. Изменение размера и управление этой памятью полностью ваша ответственность (или ответственность контейнера, который вы можете использовать, например, std::vector управляет динамической памятью и действует как динамический массив).

Ответ №6:

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

Ответ №7:

За кулисами выделяется память, небольшой кусок кремния где-то на вашем компьютере теперь выделен для массива, который вы только new что отредактировали.

Когда вы хотите «изменить размер» своего массива, это возможно сделать только на месте, если вокруг куска кремния есть свободное пространство. В большинстве случаев вместо этого необходимо зарезервировать другой, больший фрагмент и скопировать данные, которые были в первом … и, очевидно, отказаться от первого (в противном случае у вас утечка памяти).

Это делается автоматически контейнерами STL (например std::vector , или std::deque ), но вручную, когда вы сами вызываете new . Поэтому лучшее решение во избежание утечек — использовать стандартную библиотеку вместо того, чтобы пытаться эмулировать ее самостоятельно.

Ответ №8:

int *pArray = new int; можно считать массив размером 1, и он вроде как делает то, что вы хотите «по умолчанию».

Но что, если мне нужен массив из 10 элементов? Указатели не обладают никакими магическими способностями, они просто указывают на память, поэтому:

pArray[5] = 10; просто выдаст ошибку во время выполнения (если вам повезет).

Поэтому есть возможность выделить массив необходимого размера путем вызова new type[size] .

Комментарии:

1. -1 » int *pArray = new int; можно считать массивом размером 1, и он вроде как делает то, что вы хотите «по умолчанию».» — Это нонсенс.

2. может быть, это мой плохой английский, я имел в виду, что он изначально написал, что хочет pArray = new array[]; , чтобы создание массива из 1 элемента было поведением по умолчанию, вот что new int; делает. И это почти точно массив размером 1.

3. Запрашивающий, похоже, и так сбит с толку. Теперь вы предлагаете ему смешивать new / new[] и delete / delete[] ? Если вы собираетесь динамически распределять массивы в первую очередь, вы должны быть очень осторожны и знать, что вы делаете.