Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 84, средняя оценка - 4.94
AlexP11223
36 / 37 / 4
Регистрация: 20.04.2011
Сообщений: 288
01.11.2011, 00:29     Как создать динамический массив структур? #1
А как работать с вектором если я хочу динамический массив структур?
т.е. допустим
C++
1
2
3
4
5
6
7
8
9
struct tovar
{
   string name;
   int cost;
};
 
...
 
vector <tovar> tovar_list;
И как теперь увеличить его размер на 1 и записать в этот элемент (структуру) какие-то данные (имя и цену в данном случае)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
BRcr
 Аватар для BRcr
4003 / 2292 / 155
Регистрация: 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";
Bers
Заблокирован
01.11.2011, 00:43     Как создать динамический массив структур? #3
BRcr, почему вы считаете, что указатель в векторе лучше?
AlexP11223
36 / 37 / 4
Регистрация: 20.04.2011
Сообщений: 288
01.11.2011, 00:43  [ТС]     Как создать динамический массив структур? #4
Цитата Сообщение от BRcr Посмотреть сообщение
C++
1
vector <tovar*> tovar_list; //лучше-таки указатели
Почему? Я слышал, что наоборот их тут лучше не использовать.



Цитата Сообщение от BRcr Посмотреть сообщение
C++
1
2
tovar tr;
tovar_list.push_back(&tr);
оО Как-то странно выглядит из-за создания лишней переменной.
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. Создавать объект снаружи, а в вектор попадёт копия (трата времени на дополнительное копирование)
BRcr
 Аватар для BRcr
4003 / 2292 / 155
Регистрация: 03.02.2011
Сообщений: 5,064
Записей в блоге: 10
01.11.2011, 01:25     Как создать динамический массив структур? #6
Цитата Сообщение от Bers Посмотреть сообщение
Кароче говоря: если хранить в векторе указатели, вектор не будит нести ответственность за время жизни объектов.
Если хранить в векторе сами объекты, то придётся:
1 Либо создавать объект конструктором по умолчанию, а потом настраивать.
2. Создавать объект снаружи, а в вектор попадёт копия (трата времени на дополнительное копирование)
вот поэтому указатели и получше, на мой взгляд, главное не забывать удалять, что там динамически насоздавали и всех делов...
Bers
Заблокирован
01.11.2011, 02:16     Как создать динамический массив структур? #7
Цитата Сообщение от BRcr Посмотреть сообщение
вот поэтому указатели и получше, на мой взгляд, главное не забывать удалять, что там динамически насоздавали и всех делов...
Потери времени из-за одного дополнительного копирования с лихвой компенсируются за счет того, что вам не придётся самостоятельно ловить гемморой по обеспечению безопасной работы с динамической памятью, и контролировать время жизни объекта.

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

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

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

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

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

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

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

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

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

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

Не по теме:

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

ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 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";
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
01.11.2011, 15:47     Как создать динамический массив структур? #10
Цитата Сообщение от BRcr Посмотреть сообщение
лучше-таки указатели
Но при условии их правильного использования, а не как в приведённом примере, т.к. он не правильный.
Сыроежка
Заблокирован
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 );
позволит вам добавить элемент в ваш контейнер, не беспокоясь о его расширении. Контейнер сам проделает всю необходимую работу.
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. И тоже до конца работы приложения. Потом он сам за собой почистит.

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

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

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

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

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

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

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

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

Если есть способ, как это сделать без лишнего копирования - хорошо. Если нет такого способа - ну что ж... я готов с этим смириться. Пулы памяти с лихвой компенсируют мне потери от одного лишнего копирования.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
02.11.2011, 00:35     Как создать динамический массив структур? #15
много слов
контейнер может не быть хозяином объекта - тогда возможность копирования отпадает
что по поводу примера о котором шел спор - там все-равно ошибка - указатель на стековый объект
Mr.X
Эксперт С++
 Аватар для Mr.X
2802 / 1578 / 247
Регистрация: 03.05.2010
Сообщений: 3,666
02.11.2011, 01:25     Как создать динамический массив структур? #16
Цитата Сообщение от Bers Посмотреть сообщение
Ну а какой смысл вообще в том, что бы создавать объект абы где, а указатель на него держать в массиве? (даже если это умный указатель)
Это единственный выход, если в векторе нужно хранить полиморфные объекты-потомки одного базового класса. Размеры-то у них могут быть разные.
Bers
Заблокирован
02.11.2011, 02:16     Как создать динамический массив структур? #17
Цитата Сообщение от Mr.X Посмотреть сообщение
Это единственный выход, если в векторе нужно хранить полиморфные объекты-потомки одного базового класса. Размеры-то у них могут быть разные.
Ну я бы сказал - это единственный способ сделать простую имитацию, что якобы полиморфы живут в одном массиве.

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

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

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

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

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

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

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

Так это, если без указателей, то как делать? Только вариант из 5 поста? А потом обращаться по tovar_list.back()->name и tovar_list[5]->name и т.д?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.11.2011, 13:30     Как создать динамический массив структур?
Еще ссылки по теме:

C++ как создать массив структур?
Динамический массив структур C++
Как создать динамический массив типа string? Как создать класс такого массива? C++

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

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
02.11.2011, 13:30     Как создать динамический массив структур? #20
Nubik756, Сделать конструктор. Хранить элементы не через указатель. Класть в вектор созданные объекты.
Yandex
Объявления
02.11.2011, 13:30     Как создать динамический массив структур?
Ответ Создать тему
Опции темы

Текущее время: 08:10. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru