Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 84, средняя оценка - 4.94
AlexP11223
54 / 55 / 19
Регистрация: 20.04.2011
Сообщений: 353
#1

Как создать динамический массив структур? - C++

01.11.2011, 00:29. Просмотров 11959. Ответов 39
Метки нет (Все метки)

А как работать с вектором если я хочу динамический массив структур?
т.е. допустим
C++
1
2
3
4
5
6
7
8
9
struct tovar
{
   string name;
   int cost;
};
 
...
 
vector <tovar> tovar_list;
И как теперь увеличить его размер на 1 и записать в этот элемент (структуру) какие-то данные (имя и цену в данном случае)
http://www.cyberforum.ru/cpp-beginners/thread1899659.html
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.11.2011, 00:29
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Как создать динамический массив структур? (C++):

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

C++ Как удалить динамический массив структур
Как удалить массив структур, который был создан через new? Через deletedata,...

Как ввести данные в динамический массив структур?
Подскажите пожалуйста, можно ли вводить данные в динамический массив структур c...

Как создать динамический массив типа string? Как создать класс такого массива?
Как создать динамический массив типа string? Как создать класс такого массива? ...

Динамический массив структур
Помогите пожалуйста с заданием Создать динамический массив структур (не менее...

39
BRcr
4015 / 2305 / 291
Регистрация: 03.02.2011
Сообщений: 5,064
Записей в блоге: 10
01.11.2011, 00:38 #2
C++
1
2
3
4
vector <tovar*> tovar_list; //лучше-таки  указатели
tovar tr;
tovar_list.push_back(&tr);
tovar_list[0]->name = "orange";
0
Bers
Заблокирован
01.11.2011, 00:43 #3
BRcr, почему вы считаете, что указатель в векторе лучше?
0
AlexP11223
54 / 55 / 19
Регистрация: 20.04.2011
Сообщений: 353
01.11.2011, 00:43  [ТС] #4
Цитата Сообщение от BRcr Посмотреть сообщение
C++
1
vector <tovar*> tovar_list; //лучше-таки указатели
Почему? Я слышал, что наоборот их тут лучше не использовать.



Цитата Сообщение от BRcr Посмотреть сообщение
C++
1
2
tovar tr;
tovar_list.push_back(&tr);
оО Как-то странно выглядит из-за создания лишней переменной.
0
Bers
Заблокирован
01.11.2011, 01:09 #5
Цитата Сообщение от Nubik756 Посмотреть сообщение
оО Как-то странно выглядит из-за создания лишней переменной.
вектор - это контейнер, задача которого - хранение данных.
Он только хранит. Он не отвечает за создание данных.

Сам объект либо создаётся снаружи, а потом помещается в вектор (пример вы уже видели)

Либо создаётся сразу внутри:

C++
1
2
3
4
5
6
7
8
9
10
11
vector <tovar> tovar_list;  //пустой контейнер.  
                                        //Имя контейнера крайне неудачное. 
                                         //Можно спутать вектор и лист
 
 tovar_list.resize(1, tovar() ); //расширение контейнера. 
          //В нем автоматически будит создан 
          //экземпляр класса tovar, при помощи 
          //указанного конструктора
 
          //естественно, в этом случае вектор должен 
          //хранить сам объект, а не указатель на него
Добавлено через 14 минут
пардон, допустил неточность.

Внутри вектора объекты сами создаются с помощью конструкторов по умолчанию.

Либо объекты всегда создаются снаружи, а вектор в свою очередь создаёт объекты внутри себя при помощи копирующего конструктора.

Кароче говоря: если хранить в векторе указатели, вектор не будит нести ответственность за время жизни объектов.

Если хранить в векторе сами объекты, то придётся:
1 Либо создавать объект конструктором по умолчанию, а потом настраивать.
2. Создавать объект снаружи, а в вектор попадёт копия (трата времени на дополнительное копирование)
0
BRcr
4015 / 2305 / 291
Регистрация: 03.02.2011
Сообщений: 5,064
Записей в блоге: 10
01.11.2011, 01:25 #6
Цитата Сообщение от Bers Посмотреть сообщение
Кароче говоря: если хранить в векторе указатели, вектор не будит нести ответственность за время жизни объектов.
Если хранить в векторе сами объекты, то придётся:
1 Либо создавать объект конструктором по умолчанию, а потом настраивать.
2. Создавать объект снаружи, а в вектор попадёт копия (трата времени на дополнительное копирование)
вот поэтому указатели и получше, на мой взгляд, главное не забывать удалять, что там динамически насоздавали и всех делов...
0
Bers
Заблокирован
01.11.2011, 02:16 #7
Цитата Сообщение от BRcr Посмотреть сообщение
вот поэтому указатели и получше, на мой взгляд, главное не забывать удалять, что там динамически насоздавали и всех делов...
Потери времени из-за одного дополнительного копирования с лихвой компенсируются за счет того, что вам не придётся самостоятельно ловить гемморой по обеспечению безопасной работы с динамической памятью, и контролировать время жизни объекта.

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

Вектор возвращает ссылку на свой объект.
Если он возвращает ссылку на реальный объект - вы получаете доступ к этому объекту по этой ссылке.

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

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

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

Если по задаче нужно постоянно перемешивать внутри вектора объекты с места на место, то сделать можно так: создаются два вектора. Первый содержит сами объекты, а второй - индексы объектов в первом векторе.
Перемешивают индексы, сами же объекты остаются неподвижными.

Вызывающая сторона забирает индекс. А зная индекс, забирает ссылку на сам объект.
Если обернуть пару векторов в один класс, можно получить замечательный контейнер, который позволяет как бы "быстро перемешивать объекты".

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

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

Таким образом достигается шустрая работа, а на плечи крепкого парня по имени std::vector сваливается вся ответственность за безопасность.
1
BRcr
01.11.2011, 12:54
  #8

Не по теме:

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

0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
01.11.2011, 15:06 #9
Лучше юзать shared-ы если имеется желание юзать указатели.

C++
1
2
3
4
5
6
7
8
9
10
11
12
struct tovar
{
   string name;
   int cost;
};
 
typedef std::shared_ptr<tovar> tovar_ptr;
 
std::vector <tovar_ptr> tovar_list;
 
tovar_list.push_back(tovar_ptr(new tovar());
tovar_list.back()->name = "name";
0
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1306 / 1221 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
01.11.2011, 15:47 #10
Цитата Сообщение от BRcr Посмотреть сообщение
лучше-таки указатели
Но при условии их правильного использования, а не как в приведённом примере, т.к. он не правильный.
0
Сыроежка
Заблокирован
01.11.2011, 19:37 #11
Цитата Сообщение от Nubik756 Посмотреть сообщение
А как работать с вектором если я хочу динамический массив структур?
т.е. допустим
C++
1
2
3
4
5
6
7
8
9
struct tovar
{
   string name;
   int cost;
};
 
...
 
vector <tovar> tovar_list;
И как теперь увеличить его размер на 1 и записать в этот элемент (структуру) какие-то данные (имя и цену в данном случае)
Сначала некотрое отступление. Уже имеется конструкция, которая реализует вашу структуру. Это шаблонный класс std:air Так что вы можете определить свой объект tovar, как

C++
1
std::pair<std::string, int> tovar;
Что касается вектора, то это контейнер, который расширяется по мере добавления в него элементов. Элементы добавляются с помощью методов этого контейнера, например, метода push_back - добавить элемент в конец контейнера, или insert - добавить элемент в нужное место в контейнере.

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

C++
1
tovar_list.push_back( tovar );
позволит вам добавить элемент в ваш контейнер, не беспокоясь о его расширении. Контейнер сам проделает всю необходимую работу.
0
Bers
Заблокирован
01.11.2011, 23:43 #12
Цитата Сообщение от ForEveR Посмотреть сообщение
tovar_list.push_back(tovar_ptr(new tovar());
tovar_list.back()->name = "name";
У меня к вам несколько вопросов:

1. Насколько безопаснее предоставить вектору самостоятельно построить объект с конструктором по умолчанию, по сравнению с внешним явным вызовом new tovar() ?
( При условии, что сами объекты исключений не кидают. И если и могут кинуть - то только потому, что агрегируют внутри себя другие вектора).

2. Насколько безопаснее сначала создать объект на стеке, а потом предоставить вектору самостоятельно выделить память под объект, и скопировать его к себе при помощи конструктора копирования, по сравнению с внешним явным вызовом new tovar() ?
( При условии, что сами объекты исключений не кидают. И если и могут кинуть - то только потому, что агрегируют внутри себя другие вектора).


Я просто так и не нашёл нигде информации о том, как именно вектор обеспечивает безопасную работу с памятью. Единственное, что я нашёл, это что теоретически он может кинуть bad_alloc.
И у меня возник вопрос: а он вообще хоть чем нибудь принципиально отличается от голого new в в плане безопасности?

Неужели, каждую операцию, которая теоретически может привести к реаллоку внутри вектора, нужно окружать ловушками исключений?

3. Создание объекта абы-где ведёт к фрагментации памяти, и падению производительности из-за кэш промахов и тп. Поэтому, однотипные объекты выгоднее держать в едином блоке данных.
(это не я придумал, это я вычитывал в умных книжках. Так что ногами не бейте).

Соответственно, выгоднее держать объекты в векторах, а не "просто так".
Но тогда их уже не подцепишь к интеллектуальному указателю. Потому что, если объект по факту живёт в векторе, всегда есть вероятность, что вектор сделает реалок, и все внешние ссылки станут не валидными.

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

Мне единственное, что пришло в голову - это объектный пул памяти.
Пул создаёт вектор на 256 объектов. И этот вектор обречен всю жизнь иметь только 256 объектов. Объекты никак не перемешиваются. Они только помечаются как "занятый", или "свободный".

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

Не хватило 256 мест - пул ещё один такой же сделает, теперь будит 512. И тоже до конца работы приложения. Потом он сам за собой почистит.

Но при таком подходе, единственное, зачем может быть нужен интеллектуальный указатель - это контролировать сколько внешних пользователей ссылаются на объект (ну то есть, можно его уже пометить как "свободный", или ещё нельзя. А если в конце работы, на момент ликвидации пула окажется, что на его объекты ещё кто то там снаружи ссылается - значит где то там наверху была допущена "утечка").

Вопрос такой, а можно добиться схожего эффекта, только как нить попроще?
Объектный пул в некоторых специфических ситуациях мне кажется излишним...
Нужно, что бы объекты создавались в массивах, но внешние ссылки не боялись реаллоков.
Что бы можно было бы спокойно добавлять объекты, и удалять.

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

А покамест, я вот сейчас сижу и думаю, ничто же не мешает сделать специализированный смартпоинтер, который завязан на индексе объекта в векторе, а не его указателе...
0
alex_x_x
бжни
2454 / 1660 / 134
Регистрация: 14.05.2009
Сообщений: 7,162
01.11.2011, 23:51 #13
Bers, речь вообще обычно не об опасности/безопасности, а о том, что происходит копирование
ссылки же контейнеры держать не умеют, остается использовать указатели
0
Bers
Заблокирован
02.11.2011, 00:18 #14
Цитата Сообщение от alex_x_x Посмотреть сообщение
Bers, речь вообще обычно не об опасности/безопасности, а о том, что происходит копирование
ссылки же контейнеры держать не умеют, остается использовать указатели
Ну а какой смысл вообще в том, что бы создавать объект абы где, а указатель на него держать в массиве? (даже если это умный указатель)

Смысл делать вид "будто бы объект живет в массиве", если он там не живет?

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

Использовать вектор смартпоинтеров только в качестве центральной точки доступа к разбросанным по всей памяти объектам?
И это только ради того, что бы избежать одного лишнего копирования?

Меня лично интересует главным образом вопрос безопасности, и как сделать так, что бы объекты жили в непрерывном блоке памяти, и при этом внешние ссылки не боялись бы реаллоков, если я захочу подселить к объектам ещё одного пассажира.

Если есть способ, как это сделать без лишнего копирования - хорошо. Если нет такого способа - ну что ж... я готов с этим смириться. Пулы памяти с лихвой компенсируют мне потери от одного лишнего копирования.
0
alex_x_x
бжни
2454 / 1660 / 134
Регистрация: 14.05.2009
Сообщений: 7,162
02.11.2011, 00:35 #15
много слов
контейнер может не быть хозяином объекта - тогда возможность копирования отпадает
что по поводу примера о котором шел спор - там все-равно ошибка - указатель на стековый объект
0
Mr.X
Эксперт С++
3178 / 1705 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
02.11.2011, 01:25 #16
Цитата Сообщение от Bers Посмотреть сообщение
Ну а какой смысл вообще в том, что бы создавать объект абы где, а указатель на него держать в массиве? (даже если это умный указатель)
Это единственный выход, если в векторе нужно хранить полиморфные объекты-потомки одного базового класса. Размеры-то у них могут быть разные.
0
Bers
Заблокирован
02.11.2011, 02:16 #17
Цитата Сообщение от Mr.X Посмотреть сообщение
Это единственный выход, если в векторе нужно хранить полиморфные объекты-потомки одного базового класса. Размеры-то у них могут быть разные.
Ну я бы сказал - это единственный способ сделать простую имитацию, что якобы полиморфы живут в одном массиве.

Я с вашего позволения перефразирую вашу фразу:
"Если по задаче требуется единая точка доступа к группе объектов, создаётся вектор умных указателей на эти объекты".

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

Но в том месте, где происходит непосредственно создание самого объекта, допустим, в недрах специализированной фабрики: CBase* ob = new CConcreteOb; можно решить жилищный вопрос реального объекта.

Для полиморфов можно создать несколько массивов.
Каждый конкретный объект определяется на местожительство в свой массив, а наружу отдаётся смартпоинтер на него.

Пожалуйста, вам нужна единая точка доступа к объектам - пихайте этот смартпоинтер в массив смартпоинтеров. Делайте с ним вообще все, что хотите.

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

Грамотный объектный пул памяти + ОО-архитектура == высокая скорость, и надежность.
0
Jupiter
Каратель
Эксперт С++
6568 / 3989 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
02.11.2011, 02:59 #18
Цитата Сообщение от Bers Посмотреть сообщение
Пожалуйста, вам нужна единая точка доступа к объектам - пихайте этот смартпоинтер в массив смартпоинтеров.
контейнеры создавались для удобства, и "глупый" массив не всегда удовлетворяет требованиям
0
AlexP11223
54 / 55 / 19
Регистрация: 20.04.2011
Сообщений: 353
02.11.2011, 13:28  [ТС] #19
Сначала некотрое отступление. Уже имеется конструкция, которая реализует вашу структуру. Это шаблонный класс std:air Так что вы можете определить свой объект tovar, как
На самом деле там больше полей.

Так это, если без указателей, то как делать? Только вариант из 5 поста? А потом обращаться по tovar_list.back()->name и tovar_list[5]->name и т.д?
0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
02.11.2011, 13:30 #20
Nubik756, Сделать конструктор. Хранить элементы не через указатель. Класть в вектор созданные объекты.
0
02.11.2011, 13:30
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.11.2011, 13:30
Привет! Вот еще темы с решениями:

Динамический массив структур
Нужно сделать динамический массив структур. Задание составить перечень стран и...

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

Динамический массив структур ...
Как создать дин. массив структур....пользователь должен ввести число этих...

Динамический массив структур С++
Мне нужно сделать добавление экземпляра структуры в массив. Для этого нужно...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru