С Новым годом! Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/9: Рейтинг темы: голосов - 9, средняя оценка - 4.56
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712

Добавление своего типа данных в map

04.12.2019, 15:36. Показов 1971. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую всех. Сделал тестовый пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class A
{
  public:
  A()  { cout << "A() " << endl;  }
  ~A() { cout << "~A() " << endl; }
};
 
int main()
{
  map<string, A> m;
  m.insert(make_pair<string, A>("one", A()));
  return 0;
}
Объясните, пожалуйста, почему при запуске кода конструктор выполняется один раз, деструктор 3 раза! Последний вызов деструктора понятен: контейнер m выходит за область видимости. Но откуда еще 2 деструктора и где относящиеся к ним конструкторы?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.12.2019, 15:36
Ответы с готовыми решениями:

Нужен совет по созданию своего типа данных
Приветствую всех. Мне необходимо создать свой тип данных &quot;Пароль&quot;. Размер самого пароля всегда один и тот же и составляет 6 байт. Кроме...

Передача в контейнер map пользовательского типа данных
Доброго времени суток, дамы и господа. Интересует такая задачка: создать контейнер типа map, который будет хранить пользовательский тип...

sort для своего типа данных
#include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;algorithm&gt; using namespace std; class foo { public: foo() : v(0)...

18
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
04.12.2019, 16:33
Цитата Сообщение от d7d1cd Посмотреть сообщение
Объясните, пожалуйста, почему при запуске кода конструктор выполняется один раз, деструктор 3 раза! Последний вызов деструктора понятен: контейнер m выходит за область видимости. Но откуда еще 2 деструктора и где относящиеся к ним конструкторы?
У тебя там объект перемещается несколько раз - сначала в std::pair, потом в map, на каждое перемещение отрабатывает деструктор

Добавлено через 1 минуту
Используй emplace, вместо insert
C++
1
m.emplace("one");
1
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
04.12.2019, 16:38  [ТС]
oleg-m1973, спасибо. Но есть проблема. У меня система, где у map нет метода emplace. Как быть в этом случае?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
04.12.2019, 16:43
Цитата Сообщение от d7d1cd Посмотреть сообщение
oleg-m1973, спасибо. Но есть проблема. У меня система, где у map нет метода emplace. Как быть в этом случае?
Делай как раньше, insert, там вроде всё нормально. Или тебя деструкторы смущают?
1
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
04.12.2019, 16:50  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Или тебя деструкторы смущают?
Дело в том, что на самом деле класс А не имеет конструктора по умолчанию. При создании объекта этого класса в конструктор передается имя файла и он его открывает, сохраняя идентификатор (соответственно, деструктор закрывает). При копировании в pair отработает деструктор и закроет файл. В результате, в конечном итоге, в map будет экземпляр класса А с идентификатором файла, который уже закрыт.
Не могу сообразить как выйти из этой ситуации...
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
04.12.2019, 17:00
Цитата Сообщение от d7d1cd Посмотреть сообщение
При копировании в pair отработает деструктор и закроет файл. В результате, в конечном итоге, в map будет экземпляр класса А с идентификатором файла, который уже закрыт.
Добавь конструктор перемещения, либо используй
C++
1
2
map<string, std::unique_ptr<A>> m;
m.insert(make_pair("one", std::unique_ptr<A>(new A())));
Добавлено через 1 минуту
Если unique_ptr тоже не поддерживается, сделай std::map<string, A*>, только не забывай удалять эти указатели

Добавлено через 1 минуту
Кстати, что у тебя за компилятор, может просто обновить его?
0
фрилансер
 Аватар для Алексей1153
6446 / 5641 / 1128
Регистрация: 11.10.2019
Сообщений: 15,009
04.12.2019, 18:14
в старых компиляторах можно попробовать поискать тут (в VS9 уже есть)

C++
1
2
3
#include <memory>
 
std::tr1::shared_ptr
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
05.12.2019, 08:41  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Добавь конструктор перемещения
Конструктор перемещения не доступен в моем компиляторе.

Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Если unique_ptr тоже не поддерживается, сделай std::map<string, A*>, только не забывай удалять эти указатели
unique_ptr нет. Удалять указатели... Не, не хочется применять такой вариант.

Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Кстати, что у тебя за компилятор, может просто обновить его?
За обновлением надо идти с поклоном к IBM. Работаю в системе IBM i со встроенным в нее компилятором. На этой странице используемый мной компилятор произошел от IBM XLC++. Но не все возможности перенес .

В общем, решил просто нормально запрограммировать свой класс, определив в нем не только конструктор по умолчанию, но и конструктор копирования и оператор присваивания копированием (правило трех). Так как объект класса управляет файлом, то при создании копии объекта эта копия должна управлять тем же файлом. Кроме этого, при удалении одного из объекта (оригинала или копии) необходимо учитывать, нет ли "в живых" другого объекта, который управляет тем же файлом.
Тогда можно будет спокойно использовать метод insert через make_pair.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
05.12.2019, 08:55
make_pair<const string, A>("one", A())
1
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
05.12.2019, 10:52
Цитата Сообщение от d7d1cd Посмотреть сообщение
В общем, решил просто нормально запрограммировать свой класс, определив в нем не только конструктор по умолчанию, но и конструктор копирования и оператор присваивания копированием (правило трех). Так как объект класса управляет файлом, то при создании копии объекта эта копия должна управлять тем же файлом. Кроме этого, при удалении одного из объекта (оригинала или копии) необходимо учитывать, нет ли "в живых" другого объекта, который управляет тем же файлом.
Тогда можно будет спокойно использовать метод insert через make_pair.
Лучше сделай указатели.
А ещё лучше, напиши свой класс, аналог shared_ptr, он довольно простой и решит все твои проблемы
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
05.12.2019, 11:40  [ТС]
Croessmah, добавление const избавило от одной пары конструктор копирования - деструктор. Спасибо.

Теперь столкнулся с другой проблемой.
Если обратиться в контейнере к существующему в нем элементу по ключу, то происходит вызов конструктора по умолчанию (без этого конструктора код обращения к элементу вообще не компилится), затем конструктора копирования, затем два раза деструктор.
Все усложняет еще то, что этот же код в онлайн компиляторе работает без вызова конструкторов и деструкторов при обращении к элементу.
Можете объяснить, что в моей STL библиотеке не так?

Тестируемый код:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <string>
#include <map>
using namespace std;
 
 
class IFile
{
  public:
  IFile();
  IFile(const IFile&);
  ~IFile();
};
 
IFile::IFile() {
  cout << "IFile()" << endl;
}
 
IFile::IFile(const IFile&) {
  cout << "IFile(const IFile& iFile)" << endl;
}
 
IFile::~IFile() {
  cout << "~IFile()" << endl;
}
 
 
 
int main()
{
  cout << "Начало программы --------------------------------------------------" << endl;
  map<string, IFile> Files;
  const char* File = "one";
 
  cout << "Files.insert(make_pair<const string, IFile>(File, IFile())); ------" << endl;
  Files.insert(make_pair<const string, IFile>(File, IFile()));
 
  cout << "Files[File]; ------------------------------------------------------" << endl;
  Files[File];
 
  cout << "Files.clear(); ----------------------------------------------------" << endl;
  Files.clear();
 
  cout << "Конец программы ---------------------------------------------------" << endl;
  return 0;
}


Результат моего компилятора:
Кликните здесь для просмотра всего текста
Начало программы --------------------------------------------------
Files.insert(make_pair<const string, IFile>(File, IFile())); ------
IFile()
IFile(const IFile& iFile)
IFile(const IFile& iFile)
~IFile()
~IFile()
Files[File]; ------------------------------------------------------
IFile()
IFile(const IFile& iFile)
~IFile()
~IFile()
Files.clear(); ----------------------------------------------------
~IFile()
Конец программы ---------------------------------------------------


Результат онлайн компилятора (тип компилятора выбран С++):
Кликните здесь для просмотра всего текста
Начало программы --------------------------------------------------
Files.insert(make_pair<const string, IFile>(File, IFile())); ------
IFile()
IFile(const IFile& iFile)
IFile(const IFile& iFile)
~IFile()
~IFile()
Files[File]; ------------------------------------------------------
Files.clear(); ----------------------------------------------------
~IFile()
Конец программы ---------------------------------------------------
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
05.12.2019, 11:43
Цитата Сообщение от d7d1cd Посмотреть сообщение
Если обратиться в контейнере к существующему в нем элементу по ключу, то происходит вызов конструктора по умолчанию (без этого конструктора код обращения к элементу вообще не компилится), затем конструктора копирования, затем два раза деструктор.
Потому что здесь, если элемент не найден, то он создаётся. Используй для поиска метод find
0
фрилансер
 Аватар для Алексей1153
6446 / 5641 / 1128
Регистрация: 11.10.2019
Сообщений: 15,009
05.12.2019, 11:46
d7d1cd, у make_pair можно не указывать параметры шаблона, он их выведет

C++
1
m.insert(std::make_pair("one", A()));
насчёт лишних конструкторов и деструкторов - в дебаге всё "честно" вызывается, но в релизе компилятор пооптимизирует, не будет лишноты. Однако, если ты выводишь всякие дебажные сообщения в конструкторе и деструкторе, то оптимизатор может их и не убрать

Наверное, в онлайн компиляторе тоже оптимизатор поработал
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
05.12.2019, 11:58
Цитата Сообщение от Алексей1153 Посмотреть сообщение
у make_pair можно не указывать параметры шаблона, он их выведет
В данном случае он их выведет не так как нужно.
Цитата Сообщение от d7d1cd Посмотреть сообщение
В общем, решил просто нормально запрограммировать свой класс
Вы можете в IFile добавить счетчик ссылок.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
05.12.2019, 12:25  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Потому что здесь, если элемент не найден, то он создаётся.
oleg-m1973, два вопроса:
1. Вы внимательно прочитали сообщение?
Цитата Сообщение от d7d1cd Посмотреть сообщение
Если обратиться в контейнере к существующему в нем элементу
2. Вы смотрели приведенный мной код?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
05.12.2019, 12:30
Цитата Сообщение от d7d1cd Посмотреть сообщение
oleg-m1973, два вопроса:
1. Вы внимательно прочитали сообщение?
Сообщение от d7d1cd
Я тебе написал, когда должен вызываться этотконструктор, для существующих элементов это вызова быть не должно. Что там делает твой говённый компилятор в своей библиотеке, я не знаю. Посмотри код оператора []
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
05.12.2019, 12:33  [ТС]
Цитата Сообщение от Croessmah Посмотреть сообщение
Вы можете в IFile добавить счетчик ссылок.
Так и планировал сделать.

Частично разобрался почему при обращении к существующему элементу вызываются конструкторы. Все из-за того, что в моей реализации STL оператор [] вызывает метод insert (что даже указано в справке) без предварительной проверки на существование элемента. Естественно, метод insert требует сконструированный объект.
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
05.12.2019, 15:14
Цитата Сообщение от Croessmah Посмотреть сообщение
make_pair<const string, A>("one", A())
m["one"];
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
05.12.2019, 15:18
rat0r, параметры конструктора опущены. Выше ТС написал
Цитата Сообщение от d7d1cd Посмотреть сообщение
Дело в том, что на самом деле класс А не имеет конструктора по умолчанию.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
05.12.2019, 15:18
Помогаю со студенческими работами здесь

Использование vector insert и своего типа данных
Не понимаю почему вот здесь выскакивает странная ошибка: arr.insert(arr.begin(),(*max)); #include &lt;iostream&gt; #include...

Как использовать stl для своего класса(для пользовательского типа данных)
Мне бы пример какой-нибудь а то в инете ищу ничего не могу найти, кроме базовых типов данных

Можно ли реализовать Map от своего класса?
Надо сделать что-то подобное, подскажите возможно ли такое и как? public class Main { public static void main(String args) { ...

Добавление данных типа string в список
Здравствуйте! Хочу добавлять из файла слова в список, но возникают проблемы с Parse строки. Подскажите ,пожалуйста, как это сделать и...

добавление в map
Добрый день Задача такая, я считываю из бд данные и сохраняю их в map&lt;string, int&gt;. map хранит, в себе забаненый ip и его timestamp,...


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru