Создание массива объектов в стеке и куче

Рассмотрим следующий код:

class myarray
{
    int i;

    public:
            myarray(int a) : i(a){ }

}

Как вы можете создать массив объектов myarray в стеке и как вы можете создать массив объектов в куче?


person Light_handle    schedule 21.10.2009    source источник
comment
Это вопрос домашнего задания? Это звучит как один.   -  person Amber    schedule 21.10.2009
comment
Нет... Это не вопрос домашнего задания... Нашел это в интернете, готовясь к собеседованию.... :)   -  person Light_handle    schedule 21.10.2009


Ответы (5)


Вы можете создать массив объектов в стеке с помощью:

myarray stackArray[100]; // 100 objects

И в куче (или "свободном хранилище"):

myarray* heapArray = new myarray[100];
delete [] heapArray; // when you're done

Но лучше не управлять памятью самостоятельно. Вместо этого используйте std::vector:

#include <vector>
std::vector<myarray> bestArray(100);

Вектор — это динамический массив, который (по умолчанию) размещает элементы из кучи.††


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

myarray stackArray[3] = { 1, 2, 3 };

Или с вектором:

// C++11:
std::vector<myarray> bestArray{ 1, 2, 3 };

// C++03:
std::vector<myarray> bestArray;
bestArray.push_back(myarray(1));
bestArray.push_back(myarray(2));
bestArray.push_back(myarray(3));

Конечно, вы всегда можете дать ему конструктор по умолчанию:

class myarray
{
    int i;    
public:
    myarray(int a = 0) :
    i(a)
    {}
};

† Для педантов: C++ на самом деле не имеет «стека» или «кучи»/«свободного хранилища». У нас есть продолжительность «автоматического хранения» и «динамического хранения». На практике это согласуется с выделением стека и выделением кучи.

†† Если вы хотите «динамическое» выделение из стека, вам нужно определить максимальный размер (хранилище стека известно заранее), а затем указать вектору новый распределитель, чтобы вместо этого он использовал стек.

person GManNickG    schedule 21.10.2009
comment
вы можете использовать _alloca() для динамического выделения переменных объемов памяти в стеке... - person Crashworks; 21.10.2009
comment
@GMan - это нестандартная, но широко распространенная функция C. - person Chris Lutz; 21.10.2009
comment
В C++ это работает так же, как и в C; если есть более стандартный способ указать компилятору выделить N байтов в стеке, где N определяется во время выполнения, я не знаю, что это такое. - person Crashworks; 21.10.2009
comment
может быть, просто очень маленькая деталь, я не уверен, что vector указывает, что элементы будут в куче. например, классическая реализация string сохраняет символы внутри самого объекта до 8 или 16 символов в целом. затем, когда ему нужно удлиниться, он переключается на кучу. Итак, если сам объект string находится в стеке, данные также находятся в стеке для всех строк меньше 16. Можно представить, что вектор может действовать одинаково в реализациях, нет? - person v.oddou; 24.02.2015
comment
Разве массив объектов не должен быть двойным указателем?? Поскольку каждый объект является указателем при сохранении в куче - person filip; 04.07.2019

Поскольку C++11 std::array<T,size> доступен для массивов, размещенных в стеке. Он обертывает T[size], предоставляя интерфейс std::vector, но большинство методов - constexpr. Недостатком здесь является то, что вы никогда не знаете, когда переполняете стек.

std::array<myarray, 3> stack_array; // Size must be declared explicitly.VLAs

Для массивов, выделенных с помощью динамической памяти, используйте std::vector<T>. Если вы не укажете пользовательский распределитель, стандартная реализация будет использовать память кучи для выделения элементов массива.

std::vector<myarray> heap_array (3); // Size is optional.

Обратите внимание, что в обоих случаях для инициализации массива требуется конструктор по умолчанию, поэтому вы должны определить

myarray::myarray() { ... }

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

person Alexander Solovets    schedule 07.01.2016
comment
std::array хорош тем, что - как и любая другая хорошо запрограммированная оболочка вокруг T[n] - он знает свой собственный размер (с помощью магии шаблонов), может быть передан более приятным образом, может быть возвращен из функций и т. д. Вы мне понравились никогда не знаешь, когда вы переполняете стек - ну, за исключением случаев, когда это вызывает совершенно случайное повреждение нестековой памяти и становится очень очевидным :-) но, конечно, лучше избегать выделения огромных массивов в стеке. - person underscore_d; 15.02.2016

Если вы создаете массив объектов класса myarray (либо в стеке, либо в куче), вам нужно будет определить конструктор по умолчанию.

Невозможно передать аргументы конструктору при создании массива объектов.

person Tanuj    schedule 21.10.2009

Я знаю, как создать объект из конструктора по умолчанию, но только в стеке:

Предположим, вы хотите создать 10 объектов для класса MyArray с a = 1..10:

MyArray objArray[] = { MyArray[1], MyArray[2]......MyArray[10]}

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

person Alok    schedule 03.11.2010
comment
Синтаксис? Используйте круглые скобки, в следующих случаях используется временное значение: MyArray objArray[] = { MyArray(0), MyArray(88) и т. д., } - person Hoven; 30.10.2015
comment
Как уже упоминалось, это не будет компилироваться. - person underscore_d; 15.02.2016

person    schedule
comment
Я также не вижу, где находится какой-либо массив A, если только объекты не считаются массивами размера 1. - person Peter - Reinstate Monica; 10.11.2014