Higher
1952 / 1218 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
1

Можно ли узнать размер одного элемента в STL контейнере?

23.04.2012, 10:53. Показов 3400. Ответов 4
Метки нет (Все метки)

Допустим, мне захотелось узнать, сколько памяти ест мой map. Для этого надо знать размер 1 элемента. Я погуглил, покопался в cpp-reference, но ничего полезного не нашел. Сойдут и нестандартные способы, кроме изучения исходников компилятора.
P.S. для примера
C++
1
std::map< int, int > map;
В этом примере кроме pair< int, int >, который вешает 8 байт, теоретически должны храниться еще 3 указателя, итого 1 элемент мапа на 64битной оси вешает [размер pair] + 24 байта, что довольно ощутимо, если map имеет большой размер. Но стандартом, насколько я знаю, реализация контейнеров не оговаривается, поэтому map может быть реализован более экономно. А вот проверить это я не могу =\
P.P.S. вопрос касается не только map, но и других контейнеров(к примеру, set тоже должен хранить 3 указателя). И еще unordered_map интересует.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.04.2012, 10:53
Ответы с готовыми решениями:

Как в контейнере STL перейти из последнего элемента на первый, не задумываясь о границах
Вообще пишу используя QtLibrary, но там не нашел подходящего решения. Если есть решение в STL, то...

Позиция элемента в контейнере STL кон. SET, поиск контейнер set словарь позиция
Есть код №1. Он выводить на экран позицию нужного мне слова (только если в середине 1 слово а не 2...

STL. Сортировка объектов в контейнере
Имеется список list из объектов Time (минуты:секунды). Через собственный метод...

В каком STL-контейнере лучше хранить объекты?
Есть класс, реализующий адреса class address { ... } Поискал в сети увидел 3 варианта...

4
В астрале
Эксперт С++
8045 / 4802 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
23.04.2012, 12:07 2
Ну пример для gcc...

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <map>
#include <iostream>
 
int main()
{
   std::map<std::string, std::string> map =
   {
      std::make_pair("1", "1")
   };
   for (std::map<std::string, std::string>::iterator iter = map.begin(); iter != map.end(); ++iter)
   {
      std::cout << 
      sizeof(*reinterpret_cast<std::_Rb_tree_node
      <std::map<std::string, std::string>::value_type>*>(iter._M_node)) << std::endl;
   }
}
А вот, чтобы на любом компиляторе... Никак. А зачем это нужно?
1
Эксперт С++
5037 / 2616 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 1
24.04.2012, 08:08 3
Ребят, объясните мне, пожалуйста, что это значит. В чем грандиозность задумки.
Я имею в виду, почему просто не:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <map>
#include <vector>
#include <iostream>
 
int main()
{
   std::map<int, short> map =
   {
      std::make_pair(1, 1),
      std::make_pair(2, 2)
   };
      
   std::cout << sizeof(map) + sizeof(*map.begin()) * map.size() << std::endl;
   
   std::vector<unsigned char> vector =
   {
      1, 2, 3
   };
   
   std::cout << sizeof(vector) + sizeof(*vector.begin()) * vector.capacity() << std::endl;
}
0
Higher
1952 / 1218 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
24.04.2012, 08:20  [ТС] 4
В случае с вектором никакой разницы нету, т.к. он реализован просто в виде С-массива.
Но, к примеру, в одном элементе list'a хранятся указатели на предыдущий и следующий элемент, и здесь
C++
1
sizeof(*mylist.begin())
они не учитываются.
Если верить Саттеру, то в одном элементе set/map хранится уже 3 указателя(на предыдущий элемент, на следующий элемент и на родителя), и я просто хотел это проверить, ибо книга уже слегка устарела(например, там говорится, что vector<bool> медленнее, чем vector<int>).
1
В астрале
Эксперт С++
8045 / 4802 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
24.04.2012, 08:49 5
fasked, Одного элемента. Не всего контейнера а одного элемента в контейнере. Причем не value_type-а, а по внутренней реализации. Допустим для списка:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    struct _List_node_base
    {
      _List_node_base* _M_next;
      _List_node_base* _M_prev;
      
      static void
      swap(_List_node_base& __x, _List_node_base& __y) throw ();
      
      void
      _M_transfer(_List_node_base* const __first,
          _List_node_base* const __last) throw ();
      
      void
      _M_reverse() throw ();
      
      void
      _M_hook(_List_node_base* const __position) throw ();
      
      void
      _M_unhook() throw ();
    };
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  /// An actual node in the %list.
  template<typename _Tp>
    struct _List_node : public __detail::_List_node_base
    {
      ///< User's data.
      _Tp _M_data;
 
#ifdef __GXX_EXPERIMENTAL_CXX0X__
      template<typename... _Args>
        _List_node(_Args&&... __args)
    : __detail::_List_node_base(), _M_data(std::forward<_Args>(__args)...) 
        { }
#endif
    };
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
  /// See bits/stl_deque.h's _Deque_base for an explanation.
  template<typename _Tp, typename _Alloc>
    class _List_base
    {
    protected:
      // NOTA BENE
      // The stored instance is not actually of "allocator_type"'s
      // type.  Instead we rebind the type to
      // Allocator<List_node<Tp>>, which according to [20.1.5]/4
      // should probably be the same.  List_node<Tp> is not the same
      // size as Tp (it's two pointers larger), and specializations on
      // Tp may go unused because List_node<Tp> is being bound
      // instead.
      //
      // We put this to the test in the constructors and in
      // get_allocator, where we use conversions between
      // allocator_type and _Node_alloc_type. The conversion is
      // required by table 32 in [20.1.5].
      typedef typename _Alloc::template rebind<_List_node<_Tp> >::other
        _Node_alloc_type;
 
      typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
 
      struct _List_impl 
      : public _Node_alloc_type
      {
    __detail::_List_node_base _M_node;
 
    _List_impl()
    : _Node_alloc_type(), _M_node()
    { }
 
    _List_impl(const _Node_alloc_type& __a)
    : _Node_alloc_type(__a), _M_node()
    { }
      };
 
      _List_impl _M_impl;
C++
1
2
  template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
    class list : protected _List_base<_Tp, _Alloc>

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  /**
   *  @brief A list::iterator.
   *
   *  All the functions are op overloads.
  */
  template<typename _Tp>
    struct _List_iterator
    {
      typedef _List_iterator<_Tp>                _Self;
      typedef _List_node<_Tp>                    _Node;
 
      typedef ptrdiff_t                          difference_type;
      typedef std::bidirectional_iterator_tag    iterator_category;
      typedef _Tp                                value_type;
      typedef _Tp*                               pointer;
      typedef _Tp&                               reference;
 
      _List_iterator()
      : _M_node() { }
 
      explicit
      _List_iterator(__detail::_List_node_base* __x)
      : _M_node(__x) { }
 
      // Must downcast from _List_node_base to _List_node to get to _M_data.
      reference
      operator*() const
      { return static_cast<_Node*>(_M_node)->_M_data; }
 
      pointer
      operator->() const
      { return std::__addressof(static_cast<_Node*>(_M_node)->_M_data); }
 
      _Self&
      operator++()
      {
    _M_node = _M_node->_M_next;
    return *this;
      }
 
      _Self
      operator++(int)
      {
    _Self __tmp = *this;
    _M_node = _M_node->_M_next;
    return __tmp;
      }
 
      _Self&
      operator--()
      {
    _M_node = _M_node->_M_prev;
    return *this;
      }
 
      _Self
      operator--(int)
      {
    _Self __tmp = *this;
    _M_node = _M_node->_M_prev;
    return __tmp;
      }
 
      bool
      operator==(const _Self& __x) const
      { return _M_node == __x._M_node; }
 
      bool
      operator!=(const _Self& __x) const
      { return _M_node != __x._M_node; }
 
      // The only member points to the %list element.
      __detail::_List_node_base* _M_node;
    };
Итого. Каждый элемент это _List_node_base, а если точнее _List_node<T>.
Каждый элемент списка занимает 8 + sizeof(T) байт на 32-битной машине.
Проверка.

C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <list>
 
int main()
{
   std::list<int> lst = {1};
   std::list<int>::iterator iter = lst.begin();
   std::cout << "Sizeof 1 element: " << 
      sizeof(*reinterpret_cast<std::_List_node<int>*>(iter._M_node)) << std::endl;
}
http://liveworkspace.org/code/... 50144bfbc7
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.04.2012, 08:49
Помогаю со студенческими работами здесь

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

Узнать размер элемента и применить его к другому
На элементы повешены различные class. Как сделать так что ты элемент Удалить принимал такие же...

Найти элемент в контейнере priority_queue, используя STL вские итераторы и алгоритмы
Здравствуйте, задача описана в навание темы. Можно перебрать в цикле все элементы очереди,...

Можно ли узнать размер массива в Memo
Можно ли узнать размер массива в Memo1 и вы вести его на экран ShowMessage Пробывал так не вышло....


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru