0 / 0 / 0
Регистрация: 26.09.2014
Сообщений: 17
|
|
1 | |
А что под капотом у vector?25.07.2018, 18:32. Показов 3012. Ответов 13
Метки нет (Все метки)
Не знаю куда написать и вроде тем отвечающий на вопрос не нашел.
Вопрос заключается в том, что мне прекрасно известно, что такое шаблоны функций и классов, и какие минусы они имеют, в том числе что реализацию, должна быть в том же файле. Интересно, а как решена эта проблема в стандартных контейнерах, на примере vector. Мне кажется он как-то сохраняет внутри своего состояние тип данных. Может не прав, мне для лучшего понимания, как устроен язык.
0
|
25.07.2018, 18:32 | |
Ответы с готовыми решениями:
13
Под капотом вызова функции Что под капотом std::mutex Нюансы синтаксиса: что означает запись vector<int*> a и vector <int>*a ? Перегрузка операторов под vector |
1468 / 1009 / 456
Регистрация: 30.10.2017
Сообщений: 2,800
|
|
25.07.2018, 18:35 | 2 |
Сообщение было отмечено sed99 как решение
Решение
1
|
зомбяк
1584 / 1218 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
|
25.07.2018, 18:43 | 3 |
Если IDE поддерживает пошаговую отладку внутри стандартной библиотеки, то вполне сможешь убедиться, что в ней реализация стандартных контейнеров как раз и находится в заголовочных файлах.
Прятать реализацию полностью в cpp-файлы можно только в том случае, если "снаружи" (в заголовочных файлах, передаваемых для компиляции) не используются никакие внутренние шаблоны.
0
|
Комп_Оратор)
|
|
25.07.2018, 18:56 | 4 |
Сообщение было отмечено sed99 как решение
Решение
sed99,
Тип это не состояние. Это богатство. Причём времени компиляции. Там внутри масссив обычно. Начиная с С++/11 он доступен. По умолчанию аллокатор -
allocator<T> . Память выделяется в куче, то есть. А раздельная компоновка шаблонов не случилась.
1
|
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
|
|
25.07.2018, 19:29 | 5 |
Никак. И вообще, там есть куда более серьезная проблема - алгоритм расширения массива методом "создать новый массив побольше и скопировать в него старый". HEAP_REALLOC_IN_PLACE_ONLY? Не, не слышали (мало ли что аналоги не в любом менеджере памяти есть, это не повод вообще игнорировать существование подобных функций).
У std::map значительную часть кода (ребалансировка красно-черного дерева) вполне можно вынести из шаблона и запихать в cpp.
0
|
25.07.2018, 20:32 | 6 |
Renji, и в чём тут проблема? Ничего, что это известная фича С++ как языка, которую учитывают при написании программ? (специально, например не сорханяя указателей, ссылок и итераторов на элементы на постоянной основе)
В чём вообще выгода от использования HEAP_REALLOC_IN_PLACE_ONLY? Использовать в каких-то программах, которые не приемлют копирование данных вообще? Но если она сфейлит, придётся всё равно расширяться копированием массива пусть потом, но рано или поздно, а значит и она не подойдёт для этой задачи. Или будет такая программа в зависимости от наличия heapa либо продолжать работу либо вообще завершаться типа "ну извините, мы завели кучу указателей, ссылок и итераторов на элементы вектора и теперь не можем его расширить, попробуйте перезагрузить компьютер"
0
|
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
|
|
25.07.2018, 20:57 | 7 |
Выгода в константной сложности такой реаллокации (менеджер памяти просто меняет запись "размер блока"). Но, разумеется, в случае если in place провалилось, нам придется откатиться на классический алгоритм, с классической же линейной сложностью.
Плюс, мы снижаем требования к памяти. Представьте что массив занимает сто мегабайт, а свободно только пятьдесят. In place реаллокация вполне может сработать даже в таких условиях. А вот классическое "создать новый массив" гарантированно провалится.
0
|
0 / 0 / 0
Регистрация: 26.09.2014
Сообщений: 17
|
|
26.07.2018, 10:44 [ТС] | 8 |
Нет. Не слышал. Спасибо, что открыл такую истину простую.
----------------------------------------------------------------------------- Это работает так, сначала мы выделяем кучу, потом в этой куче мы работает из нашей структуры данных, используя шаблоны, при этом раздельной компоновки шаблона не будет? У меня правильное понимание процесса?
0
|
зомбяк
1584 / 1218 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
|
26.07.2018, 10:59 | 9 |
Неправильное. Вначале в шаблон подставляются/подбираются параметры, с которыми он должен быть скомпилирован, потом он вместе со всеми прочими функциями компилируется, и во время выполнения, если речь идёт о стандартных контейнерах, часто состоит из двух частей - одна часть в стеке и с её помощью мы управляем содержимым контейнера, и есть вторая, в куче, в которой содержатся данные, которыми управляет контейнер.
Раздельной компоновки шаблона не может быть из-за того, что до тех пор, пока не известны параметры (т.е. типы данных) с которыми он будет работать, скомпилировать(т.е. преобразовать в машинный код) шаблон невозможно.
0
|
Комп_Оратор)
|
|
26.07.2018, 14:18 | 10 |
Нет. Буквально ничего понимать не нужно.
По умолчанию вектор выделяет память в куче. Кучу выделять не нужно, - тут вообще нечего бояться. Как уже сказали есть такой момент когда выделенной памяти недостаточно и производится реалокейт. Что касается состояния связанного с типом, то нет состояния. Состояние это действительно набор данных, которые можно созранить, изменить... Тип задаётся на этапе компиляции. И на этом же этапе выводится тип вектора - инстанциируется шаблон. То есть vector<int> и vector<double> это разные типы (разные инстансы одного шаблона vector<typename T> ). Именно понимание того, что шаблон класса это верно, но редко используется, а шаблонный класс, это неверно и поэтому используется на каждом шагу, может помочь различить задачу компилятора работающего с типом и его же задачу при работе с шаблоном типа. Когда линкер видит объявление он ищет реализацию для связывания вызывающего кода и вызываемого кода. Это собственно уже объектные файлы на тот момент. Но если мы имеем дело с инстанциированием, то код типа ещё нужно сгенерировать, а потом связывать. Поэтому, не удался замысел, касающийся таинственного слова export : (тут была ссылка на stackoverflow которую сервер удалил). Прогуглите ключевое слово export C++ и вы её увидите. Это касается не столь контейнеров, сколь шаблонов как таковых. Почему никто из разработчиков компиляторов не нашёл удовлетворительного способа поддерживать данную возможность я написал. Но повторять, это механически как детскую считалку не имеет смысла.
1
|
0 / 0 / 0
Регистрация: 26.09.2014
Сообщений: 17
|
|
26.07.2018, 14:29 [ТС] | 11 |
Так, на момент компиляции заместо шаблона класса, мы получаем для данного типа данных свой вид класса, (вопрос, если два раза использовать тип данных int, будет создан два вида класса для int'а или нет?)? И про две части, можно чуть более раскрыто. Первый это просто интерфейс - vector, второй работает не посредственно с кучей - это allocator? Понимаю, что для многих это очевидная вещь, но мне до этого с таким не приходилось сталкиваться, и это момент важен для дальнейшего понимания.
0
|
Комп_Оратор)
|
|
26.07.2018, 14:42 | 12 |
sed99, контейнер stl это вид шаблона. Вы изучаете вид шаблона не имея начального представления о том, что из себя представляет шаблон. Это бессмыслесное занятие.
не будет. Класс один и тот же. Используя typedef или using можно объявить синоним типа и использовать только его для объевления объектов.
0
|
зомбяк
1584 / 1218 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
|
26.07.2018, 15:14 | 13 |
Сообщение было отмечено sed99 как решение
Решение
Один и тот же шаблон с одним и тем же набором параметров (например std::vector<int>) рассматривается как один и тот же класс.
Лучше сказать так "объект vector использует инструмент allocator для выполнения нужных действий над кучей". Но ранее написал не об этом, а о том, что в результате в памяти vector хранится в двух местах - в стеке как локальная/глобальная переменная (с полями, содержащими размер, размер выделенной в куче памяти, адрес данных в куче) и в куче, как некий динамически выделенный массив с данными. При командах, не связанных с пересозданием места в куче vector использует свои собственные алгоритмы работы с данными и указатель на них, а если пересоздание места требуется, то используются как свои, так и алгоритмы allocator'а, заданного в качестве одного из параметров шаблона у vector'а (если этот параметр не указан, используется аллокатор по-умолчанию).
1
|
0 / 0 / 0
Регистрация: 26.09.2014
Сообщений: 17
|
|
26.07.2018, 17:26 [ТС] | 14 |
0
|
26.07.2018, 17:26 | |
26.07.2018, 17:26 | |
Помогаю со студенческими работами здесь
14
Выделение памяти под vector, размером 2^1000 Отличие выделения адресатов памяти под vector error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall Vector<int>::Vector<int>(void)" (?0?$Vector@H@@QAE@XZ) в функции _main Как можно увеличить размер вектора, который является элементом вектора vector<vector<int>>arr(n, vector <int>) Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |