2015-03-19 3 views
0

У меня есть-структуру, как это:C++ структура, как создать-структуру объектов динамически,

struct MYSTRUCT { 
    .... 
}; 

если я создаю объекты структуры с цикл, как это:

for(int i = 0; i < 2; i++){ 
    MYSTRUCT *mystruct; 
} 

будет mystruct быть то же самое каждый раз из-за того же имени? В чем разница между выше кодом и этим кодом:

MYSTRUCT *mystruct0; 
MYSTRUCT *mystruct1; 

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

MYSTRUCT *mystruct0; 
MYSTRUCT *mystruct1; 
... 
MYSTRUCT *mystruct99; 
MYSTRUCT *mystruct100; 

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

vector<MYSTRUCT *> mystructs; 
for(int i = 0; i < 100; i++){ 
    MYSTRUCT *mystruct; 
    mystructs.push_back(); 
} 
+4

Ваш поиск концепции «Массив». – JBL

+0

Сделайте шаг назад. Вам нужно использовать указатели на структуры вообще? Почему вы делаете то, что делаете? –

+0

Я не думаю, что указатель - это то, что вы хотите. Если вы новичок в этой памяти, каждый из них будет уникальным, имя не имеет значения. Хотя JBL прав, то, что вы ищете, называется массивом. Или список/вектор. – marsh

ответ

1

В вашем примере кода:

for(int i = 0; i < 2; i++){ 
    MYSTRUCT *mystruct; 
} 

Вы не создаете объекты на всех. Все, что вы делаете, это Объявление Указатели на MYSTRUCT. Эти указатели неинициализированы и поэтому не указывают ни на что (пока). Более того, указатель (mystruct) сам выделяется в стеке и имеет время жизни, ограниченное областью вашего цикла for-loop.

Я не уверен, чего вы пытаетесь достичь, но если вам нужно несколько объектов типа MYSTRUCT, вы не должны пытаться их создать в таком цикле. Скорее, объявите массив или std::vector и выполните инициализацию соответствующим образом. Я оставлю это вам, чтобы выяснить, как это сделать. Когда вы это сделаете, помните о различии между статическими и динамическими массивами и их последствиях для управления памятью!

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

vector<MYSTRUCT *> mystructs; 
for(int i = 0; i < 100; i++){ 
    MYSTRUCT *mystruct; 
    mystructs.push_back(); 
} 

Что происходит здесь вы объявляете пустой вектор указателей на MYSTRUCT. Все идет нормально. Теперь, судя по телу, вы хотите заполнить этот вектор указателями на реальные объекты, но это не происходит в вашем коде. Я сомневаюсь, что это даже скомпилируется, учитывая, что push_back требует в качестве аргумента MYSTRUCT*. Поэтому, чтобы делать то, что вы собираетесь делать, ваш код должен в каждой итерации:

  1. Выделяет объект на куче.
  2. Наведите указатель на этот объект в обратном направлении от вектора.

Это будет выглядеть следующим образом:

vector<MYSTRUCT*> vec; 
for (int i = 0; i != n; ++i) // pre-incr is good practice! 
    vec.push_back(new MYSTRUCT); // optionally add constructor arguments 

Однако, это вводит вас новые обязанности: ты один запрос памяти явно с помощью new, поэтому вы должны освободить память явным образом с помощью delete.Если MYSTRUCT является полиморфным (содержит виртуальных членов), вы можете легко обойти это (даже это - полиморфный, вы не должны этого делать, но это еще одна тема).

Ответ на этот вопрос: не хранить указатели, хранить объекты:

vector<MYSTRUCT> vec; // no pointer! 
for (int i = 0; i < 100; ++i) 
    vec.push_back(MYSTRUCT()); // create an unnamed instance and copy to the back of the vec 

Там, вы только что создали вектор n экземпляров MyStruct. Нет указателей, нет new и delete, просто и легко!

+0

вы могли бы объяснить немного бит мой последний вопрос? – Tom

1

struct является типом данных, который вы определили, когда вы делаете MYSTRUCT *mystruct вы объявляете указатель к MYSTRUCT объекта и указатель называется mystruct Это то же самое, что вы делаете с int *pointer_to_int.

Для вашей первой версии вы обновляете mystruct на каждой итерации, а вторая объявляет две независимые переменные. Если вы хотите легко объявить набор MYSTRUCT*, используйте массив MYSTRUCT*: MYSTRUCT* mystruct_pointers_array[100].

ПримечанияMYSTRUCT* указателей отличаются от MYSTRUCT переменных, вам необходимо разыменования указателя для доступа к элементам MYSTRUCT. Например. mystruct->x.

0

Используйте зЬй :: вектор для этой цели:

std::vector<MYSTRUCT *> v(100); 
for (auto& pointer : v) 
    pointer = new MYSTRUCT(/*...*/); //initializating (writing address to pointer) 

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

+2

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

+0

Ваш пример не будет компилироваться, если вы укажете 'pointer' как ссылку' const'. –

+0

@JorenHeit Я тоже новичок. Я буду помнить об этом, спасибо. Но что, если мы будем использовать вектор unique_ptr-s && make_unique в этом случае? – drewpts

0

Другие говорили подобные вещи, но конкретно я хотел бы сделать это следующим образом:

std::vector <MYSTRUCT *> vect; 
for(int i = 0; i < 2; i++){ 
    vect.push_back(); 
} 

Тогда вы можете просто получить доступ к каждому элементу как массив, как vect[0]. Плюс с std::vector вы можете получить доступ к первому элементу (элемент 0) с vect.front() и последним с vect.back().

Хотя это бесполезно без назначения MYSTRUCT, который был инициализирован отдельно, я могу видеть полезность векторов struct *.

+0

это не имеет никакого смысла. – zoska

+0

@zoska извините ... что я сделал не так? – aerandir1066

+0

Прежде всего, он не будет компилироваться (пустой 'push_back()'). Во-вторых, даже если бы он (и использовал конструктор по умолчанию), то почему бы просто не инициализировать 'vector' с элементами по умолчанию? Наконец, вы не указали на необходимость использования 'new' и' delete', а также не предлагать интеллектуальных указателей или вообще не использовать никаких указателей. – zoska

2

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

Вы должны использовать контейнер (например, в вашем примере std::vector), который именно то, что вы хотите: что-то, чтобы поставить несколько других вещей того же типа.

В вашем примере:

struct MyStruct { // Don't name your struct in all caps. 
        // it's generally reserved for MACROS. Use CamelCase 
    // blablabla 

} 

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

vector<MyStruct> mystructs; 
for(int i = 0; i < 100; i++){ 
    mystructs.emplace_back(MyStruct{}); 
} 

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

Если вам нужно использовать динамическое выделение вы можете сделать что-то вроде этого:

vector<MyStruct*> mystructs; 
for(int i = 0; i < 100; i++){ 
    mystructs.emplace_back(new MyStruct{}); 
} 

Теперь вектор содержит указатели, а не объекты. Каждый объект выделяется индивидуально в своей собственной памяти, поэтому нет гарантии, что они находятся рядом друг с другом. Это очень важно для исполнения: указатели дают вам косвенное отношение. Неприкосновенность ведет к боли. Боль ведет к гневу ... blablabla => Добро пожаловать в темную сторону.

Смежные вопросы