c ++ Vector, що відбувається, коли він розширюється/перерозподіляється на стек?

Я новачок в C ++, і я використовую векторний клас у моєму проекті. Я виявився цілком корисним, оскільки я можу мати масив, який автоматично перерозподіляється кожного разу, коли це необхідно (тобто, якщо я хочу push_back елемент, і вектор досяг максимальної ємності, він знову перерозподіляється, вимагаючи більше місця в операційній системі), так що доступ до елемента вектора дуже швидкий (це не схожий на список, для досягнення елемента «n-го» я ​​повинен пройти перші елементи «n»).

Я виявив, що це питання дуже корисно, тому що в їхніх відповідях було чітко пояснено, як "розподільник пам'яті" працює, коли я хочу зберегти мій вектор у купі/стекі:

[1] vector vect;
[2] vector *vect = new vector;
[3] vector vect;

Проте сумнівається, що я трохи врятував мене, і я не можу знайти свою відповідь: Кожного разу, коли я будую вектор і починаю натискати багато елементів, він досягне моменту, коли вектор буде заповнено, тому для продовження росту його потрібно буде перерозподілити, скопіювати себе в нове місце та потім продовжувати показувати елементи pushing_back (очевидно, це перерозподіл приховано від реалізації класу, тому він повністю прозорий )

Добре, якщо я створив вектор на купі [2], я не маю проблем з уявленням про те, що може статися: клас векторні викликів malloc, набуває нового простору, а потім копіює себе в нову пам'ять і, нарешті, видаляє стару пам'ять, яка дзвонить безкоштовно.

Однак завіса приховує те, що відбувається, коли я будую вектор на стек [1]: що це трапляється, коли вектор повинен перерозподіляти? AFAIK, кожен раз, коли в C/C ++ ви вводите нову функцію, комп'ютер буде виглядати на декларації змінних, а потім розгорнути стек, щоб отримати необхідний пробіл, щоб додати ці змінні, але ви не можете виділити більше місця на стекі, коли функція вже працює. Як вектор класу вирішує цю проблему?

10
Очевидно, відповіді в цьому питанні це не зовсім пояснили, тому що у вас виникла цілком неправильна ідея.
додано Автор R. Martinho Fernandes, джерело
Вектори виділяють свої дані де-небудь, що може зростати під час виконання. Сам розмір самого векторного об'єкта залишається фіксованим, оскільки він зберігає фіксований розмір до цих динамічно виділених даних.
додано Автор juanchopanza, джерело
Це загальне невірне уявлення про те, що саме тому, що ви говорите std :: vector <...> myvect; vs. std :: vector <...> * myvect = new std :: вектор <...>; - для вмісту (!) - з розподілом стеку на першому, але розподілу купи на останньому . Не так; у той час як для випадку new ... купе набагато гарантовано, внутрішня реалізація тип контейнера вирішує, що трапляється при інстанцірованні локально. Тільки певні контейнери (наприклад, std :: array ) вставляють їх вміст. std :: vector не має.
додано Автор FrankH., джерело
Гаразд, з відповідями нижче, я розумію, що структура даних векторного об'єкта: наприклад, @juanchopanza, вказаний нижче, це набір покажчиків, який визначає розмір масиву, розташованого на купі, з об'єктами, що зберігаються на ньому. Оскільки цей масив знаходиться на купі, його можна перерозподілити, якщо потрібно більше місця. До речі, вибачте за англійську граматику! Я сподіваюсь поліпшити його з практикою!
додано Автор Karl, джерело

10 Відповіді

Ви написали

[...] скопіюйте себе в нове місце [...]

що не так, як працює вектор. Векторні дані копіюються в нове місце, а не в самий вектор.

Моя відповідь повинна дати вам уявлення про те, як вектор розроблений.

Загальний std :: векторний макет *

Примітка. std :: allocator фактично може бути порожнім класом, і std :: vector , ймовірно, не міститиме екземпляр цього класу. Це може бути неправдою для довільного розподілу.

std::vector layout

У більшості реалізацій він складається з трьох вказівників де

  • begin points to the start of the data memory of the vector on the heap (always on the heap if not nullptr)
  • end points one memory location past the last element of the vector data -> size() == end-begin
  • capacity points on memory location past the last element of the vector memory -> capacity() == capacity-begin

Вектор на стек

We declare a variable of type std::vector where T is any type and A is an allocator type for T (i.e. std::allocator).

std::vector vect1;

Як це виглядає як у пам'яті?

std::vector on the stack

Як ми бачимо: На купі не відбувається нічого, але змінна займає пам'ять, необхідну для всіх її членів у стекі. Там він і він залишиться там, доки vect1 не вийде з обсягу, оскільки vect1 - це просто об'єкт типу будь-якого типу double int або будь-що інше. Він буде сидіти там у своєму стековому положенні і чекати, щоб його знищити, незалежно від того, скільки пам'яті він обробляє себе на купі.

Покажчики vect1 ніде не вказують, оскільки вектор порожній.

Вектор на купі

Тепер нам потрібен покажчик на вектор і використання певного динамічного розподілу купу для створення вектора.

std::vector * vp = new std::vector;

Давайте знову подивимося на пам'ять.

std::vector on the heap

У нас є наша vp змінна на стекі, і наш вектор знаходиться на купі зараз. Знову ж таки сам вектор не буде рухатися по купі, оскільки його розмір є постійним. Лише покажчики ( begin , end , capacity ) будуть рухатися, щоб слідувати положенням даних у пам'яті, якщо відбувається перерозподіл. Давайте поглянемо на це.

Натискання елементів на вектор

Now we can start Натискання елементів на вектор. Let's look at vect1.

T a;
vect1.push_back(a);

std::vector after single push_back

Змінна vect1 все ще залишається там, де вона була, але пам'ять на купі було виділено, щоб містити один елемент T .

Що станеться, якщо ми додамо ще один елемент?

vect1.push_back(a);

std::vector after second push

  • Пробіл, виділений на купу для елементів даних, буде недостатньо (оскільки це лише одна позиція пам'яті)
  • Новий блок пам'яті буде виділено для двох елементів
  • Перший елемент буде скопійовано/переміщено до нового сховища.
  • Стара пам'ять буде вилучена.

Ми бачимо: новий регіон пам'яті інший.

Щоб отримати додаткову інформацію, давайте розглянемо ситуацію, якщо ми знищимо останній елемент.

vect1.pop_back();

Виділена пам'ять не змінюється, але останній елемент буде викликати свій деструктор, а кінцевий покажчик перемістить одну позицію вниз.

std::vector after 2x push and 1x pop

As you can see: capacity() == capacity-begin == 2 while size() == end-begin == 1

38
додано
@stanm: std :: allocator , ймовірно, порожній, але ви можете мати визначений користувачем розподіл, який вимагає екземпляр. І.е. у MSVS std :: vector містить екземпляр розподілювача, якщо він не порожній.
додано Автор Pixelchemist, джерело
@Karl: використовуйте std :: array , якщо ви хочете стек-виділений "вектор". Недоліком є ​​... його неможливо змінити. Точно тому що std: array (як контейнер, так і його вміст) знаходиться на стекі, і "переміщення навколо стек" неможливе.
додано Автор FrankH., джерело
@Pixelchemist: О, я бачу, std :: вектор по суті є іншим класом, ніж std :: вектор . І, звичайно, вам доведеться десь зберегти цей розподільник. Дякую.
додано Автор stanm, джерело
Ви впевнені в тому, що об'єкт «Allocator» займає місце в стек? sizeof (std :: vector ) повернення 12 і 24 для 32-бітної та 64-бітної архітектури відповідно. (x86_64, Ubuntu 13.04, gcc 4.7.3)
додано Автор stanm, джерело
Ну ... Я думаю, мої перші думки, що ми помиляємось щодо реалізації: оскільки дані вектора мають фіксований розмір, незалежно від того, наскільки великим є вектор, його можна зберігати в стекі без будь-яких проблем: allocator попросить більше розміру купу, а покажчики на дані зміняться. Тепер я розумію, чому не так інтуїтивно використовувати GDB, щоб побачити, які дані зберігаються на векторі. Дякую @ Піксельхімік!
додано Автор Karl, джерело

Ви написали

[...] скопіюйте себе в нове місце [...]

що не так, як працює вектор. Векторні дані копіюються в нове місце, а не в самий вектор.

Моя відповідь повинна дати вам уявлення про те, як вектор розроблений.

Загальний std :: векторний макет *

Примітка. std :: allocator фактично може бути порожнім класом, і std :: vector , ймовірно, не міститиме екземпляр цього класу. Це може бути неправдою для довільного розподілу.

std::vector layout

У більшості реалізацій він складається з трьох вказівників де

  • begin points to the start of the data memory of the vector on the heap (always on the heap if not nullptr)
  • end points one memory location past the last element of the vector data -> size() == end-begin
  • capacity points on memory location past the last element of the vector memory -> capacity() == capacity-begin

Вектор на стек

We declare a variable of type std::vector where T is any type and A is an allocator type for T (i.e. std::allocator).

std::vector vect1;

Як це виглядає як у пам'яті?

std::vector on the stack

Як ми бачимо: На купі не відбувається нічого, але змінна займає пам'ять, необхідну для всіх її членів у стекі. Там він і він залишиться там, доки vect1 не вийде з обсягу, оскільки vect1 - це просто об'єкт типу будь-якого типу double int або будь-що інше. Він буде сидіти там у своєму стековому положенні і чекати, щоб його знищити, незалежно від того, скільки пам'яті він обробляє себе на купі.

Покажчики vect1 ніде не вказують, оскільки вектор порожній.

Вектор на купі

Тепер нам потрібен покажчик на вектор і використання певного динамічного розподілу купу для створення вектора.

std::vector * vp = new std::vector;

Давайте знову подивимося на пам'ять.

std::vector on the heap

У нас є наша vp змінна на стекі, і наш вектор знаходиться на купі зараз. Знову ж таки сам вектор не буде рухатися по купі, оскільки його розмір є постійним. Лише покажчики ( begin , end , capacity ) будуть рухатися, щоб слідувати положенням даних у пам'яті, якщо відбувається перерозподіл. Давайте поглянемо на це.

Натискання елементів на вектор

Now we can start Натискання елементів на вектор. Let's look at vect1.

T a;
vect1.push_back(a);

std::vector after single push_back

Змінна vect1 все ще залишається там, де вона була, але пам'ять на купі було виділено, щоб містити один елемент T .

Що станеться, якщо ми додамо ще один елемент?

vect1.push_back(a);

std::vector after second push

  • Пробіл, виділений на купу для елементів даних, буде недостатньо (оскільки це лише одна позиція пам'яті)
  • Новий блок пам'яті буде виділено для двох елементів
  • Перший елемент буде скопійовано/переміщено до нового сховища.
  • Стара пам'ять буде вилучена.

Ми бачимо: новий регіон пам'яті інший.

Щоб отримати додаткову інформацію, давайте розглянемо ситуацію, якщо ми знищимо останній елемент.

vect1.pop_back();

Виділена пам'ять не змінюється, але останній елемент буде викликати свій деструктор, а кінцевий покажчик перемістить одну позицію вниз.

std::vector after 2x push and 1x pop

As you can see: capacity() == capacity-begin == 2 while size() == end-begin == 1

38
додано
@stanm: std :: allocator , ймовірно, порожній, але ви можете мати визначений користувачем розподіл, який вимагає екземпляр. І.е. у MSVS std :: vector містить екземпляр розподілювача, якщо він не порожній.
додано Автор Pixelchemist, джерело
@Karl: використовуйте std :: array , якщо ви хочете стек-виділений "вектор". Недоліком є ​​... його неможливо змінити. Точно тому що std: array (як контейнер, так і його вміст) знаходиться на стекі, і "переміщення навколо стек" неможливе.
додано Автор FrankH., джерело
@Pixelchemist: О, я бачу, std :: вектор по суті є іншим класом, ніж std :: вектор . І, звичайно, вам доведеться десь зберегти цей розподільник. Дякую.
додано Автор stanm, джерело
Ви впевнені в тому, що об'єкт «Allocator» займає місце в стек? sizeof (std :: vector ) повернення 12 і 24 для 32-бітної та 64-бітної архітектури відповідно. (x86_64, Ubuntu 13.04, gcc 4.7.3)
додано Автор stanm, джерело
Ну ... Я думаю, мої перші думки, що ми помиляємось щодо реалізації: оскільки дані вектора мають фіксований розмір, незалежно від того, наскільки великим є вектор, його можна зберігати в стекі без будь-яких проблем: allocator попросить більше розміру купу, а покажчики на дані зміняться. Тепер я розумію, чому не так інтуїтивно використовувати GDB, щоб побачити, які дані зберігаються на векторі. Дякую @ Піксельхімік!
додано Автор Karl, джерело

Те, як ви будуєте свій вектор (стек або купа), не має значення для цього.

See the documentation for std::vector

Внутрішньо, вектори використовують динамічно виділений масив для зберігання своїх елементів. Цей масив може знадобитися перерозподілити, щоб збільшити розмір, коли вставляються нові елементи, що передбачає виділення нового масиву та переміщення всіх елементів до нього.

Коли вектор «зростає», векторний об'єкт не зростає, лише змінюється внутрішній динамічний масив.

Що стосується його впровадження, ви можете подивитися на векторну реалізацію GCC.

Щоб зробити це простим, він оголошує вектор як клас з один захищений елемент , тип _Vector_impl .

Як видно, це оголошується як структура, яка містить три покажчика:

  • Той, який вказує на початку зберігання (і початок даних)
  • Той, що вказує наприкінці даних
  • Один для закінчення зберігання
6
додано
@Karl Якщо ви побудуєте свій вектор в стеку, тобто як у std :: vector myVector; , внутрішні дані все ще знаходяться на купі. У мене немає деталей реалізації (які можуть мінятися в будь-якому випадку), але ви можете сподіватися, що у вектору є член, який є T * data </​​code>, який виділяється при побудові за допомогою наступна заява: data = new T [DEFAULT_SIZE] .
додано Автор JBL, джерело
я збрехав - це 12 байт - я повертаю його назад
додано Автор im so confused, джерело
@ DavidRodríguez-prizes haha ​​yep, зрозумів, що так само, як ви опублікували свій коментар, спасибі!
додано Автор im so confused, джерело
@juanchopanza ха-ха, я помилявся, вибачте, я видалив мій коментар, і це більше не бентежить людей. це 3 покажчика, як зазначив Давид msdn.microsoft.com/en-us /library/vstudio/hh567368.aspx
додано Автор im so confused, джерело
@juanchopanza: Ваш коментар не повинен плутати. Вибір трьох вказівників (за винятком необхідного) або покажчика та двох size_type членів для відстеження size() та capacity() є деталі реалізації. Це не має значення, найважливіше, що вам потрібно відстежити три частини інформації. На розподільниках: розподільник за умовчанням та багато/більшість C ++ 03-сумісних розподільників, в основному, були безгромадянами, а простір можна було оптимізувати (пуста оптимізація бази), але концептуально (і практично зі стабільними розподілювачами) контейнер повинен мати розподіл.
додано Автор David Rodríguez - dribeas, джерело
@ AK4749: Ви маєте на увазі 12 байт на 32-бітній архітектурі ... 3 покажчика
додано Автор David Rodríguez - dribeas, джерело
@Karl: Спільна реалізація вектора має лише три частинки (без версії відладки): T * begin, end, * capacity; (і, можливо, розподіл, якщо його неможливо оптимізувати). Цей вектор не містить вказівників для всіх елементів, але єдиний вказівник на перший елемент та два сторожі , щоб визначити, де елементи дійсні припиняються ( end ) і де ємність закінчується ( capacity ). Додавання інших елементів вимагатиме збільшення, що, у свою чергу, скине три покажчики на різні значення, але структуру в стеку (тобто v в std :: vector v; ) не змінить його розмір
додано Автор David Rodríguez - dribeas, джерело
@Karl це може бути настільки просто, як покажчик на дані, а також дані користувачів для розміру та потужності.
додано Автор juanchopanza, джерело
"Зміст" (тобто масив фактичного , який підтримує вектор, aka std :: vector :: data() ) завжди розподіляється на купу. Для стек-виділених векторних контейнерів потрібно використовувати std :: array - він має ті самі ітератори та приклади, що й std :: vector sans здатність змінювати розмір і шаблон розміру.
додано Автор FrankH., джерело
Так, я розумію, що зміст вектора зберігається на купі (у кожному випадку я поставив своє питання), але ... Що є внутрішні дані векторного об'єкта, який у першому випадку інвенціонує в стек? Я думаю, це може бути "масив покажчика" (наприклад, класичний масив на C), що коли ви push_back елемент, векторний клас виділяє нову пам'ять на купу, а потім додає покажчик на цей масив покажчиків
додано Автор Karl, джерело
Я маю на увазі, якщо ви побудуєте вектор на купі за допомогою -> std :: vector * vector; <- Everythin це добре, цей "масив вказівника" буде перерозподілений, коли проміжок закінчиться .... але що це відбувається, коли ви будуєте свій вектор на стек? цей масив векторів буде створено на стекі замість купи, вірно? Редагувати: Звичайно, @uunchopanza, я не думав про ваш приклад ... це має сенс
додано Автор Karl, джерело

Те, як ви будуєте свій вектор (стек або купа), не має значення для цього.

See the documentation for std::vector

Внутрішньо, вектори використовують динамічно виділений масив для зберігання своїх елементів. Цей масив може знадобитися перерозподілити, щоб збільшити розмір, коли вставляються нові елементи, що передбачає виділення нового масиву та переміщення всіх елементів до нього.

Коли вектор «зростає», векторний об'єкт не зростає, лише змінюється внутрішній динамічний масив.

Що стосується його впровадження, ви можете подивитися на векторну реалізацію GCC.

Щоб зробити це простим, він оголошує вектор як клас з один захищений елемент , тип _Vector_impl .

Як видно, це оголошується як структура, яка містить три покажчика:

  • Той, який вказує на початку зберігання (і початок даних)
  • Той, що вказує наприкінці даних
  • Один для закінчення зберігання
6
додано
@Karl Якщо ви побудуєте свій вектор в стеку, тобто як у std :: vector myVector; , внутрішні дані все ще знаходяться на купі. У мене немає деталей реалізації (які можуть мінятися в будь-якому випадку), але ви можете сподіватися, що у вектору є член, який є T * data </​​code>, який виділяється при побудові за допомогою наступна заява: data = new T [DEFAULT_SIZE] .
додано Автор JBL, джерело
я збрехав - це 12 байт - я повертаю його назад
додано Автор im so confused, джерело
@juanchopanza ха-ха, я помилявся, вибачте, я видалив мій коментар, і це більше не бентежить людей. це 3 покажчика, як зазначив Давид msdn.microsoft.com/en-us /library/vstudio/hh567368.aspx
додано Автор im so confused, джерело
@ DavidRodríguez-prizes haha ​​yep, зрозумів, що так само, як ви опублікували свій коментар, спасибі!
додано Автор im so confused, джерело
@ AK4749: Ви маєте на увазі 12 байт на 32-бітній архітектурі ... 3 покажчика
додано Автор David Rodríguez - dribeas, джерело
@juanchopanza: Ваш коментар не повинен плутати. Вибір трьох вказівників (за винятком необхідного) або покажчика та двох size_type членів для відстеження size() та capacity() є деталі реалізації. Це не має значення, найважливіше, що вам потрібно відстежити три частини інформації. На розподільниках: розподільник за умовчанням та багато/більшість C ++ 03-сумісних розподільників, в основному, були безгромадянами, а простір можна було оптимізувати (пуста оптимізація бази), але концептуально (і практично зі стабільними розподілювачами) контейнер повинен мати розподіл.
додано Автор David Rodríguez - dribeas, джерело
@Karl: Спільна реалізація вектора має лише три частинки (без версії відладки): T * begin, end, * capacity; (і, можливо, розподіл, якщо його неможливо оптимізувати). Цей вектор не містить вказівників для всіх елементів, але єдиний вказівник на перший елемент та два сторожі , щоб визначити, де елементи дійсні припиняються ( end ) і де ємність закінчується ( capacity ). Додавання інших елементів вимагатиме збільшення, що, у свою чергу, скине три покажчики на різні значення, але структуру в стеку (тобто v в std :: vector v; ) не змінить його розмір
додано Автор David Rodríguez - dribeas, джерело
@Karl це може бути настільки просто, як покажчик на дані, а також дані користувачів для розміру та потужності.
додано Автор juanchopanza, джерело
"Зміст" (тобто масив фактичного , який підтримує вектор, aka std :: vector :: data() ) завжди розподіляється на купу. Для стек-виділених векторних контейнерів потрібно використовувати std :: array - він має ті самі ітератори та приклади, що й std :: vector sans здатність змінювати розмір і шаблон розміру.
додано Автор FrankH., джерело
Так, я розумію, що зміст вектора зберігається на купі (у кожному випадку я поставив своє питання), але ... Що є внутрішні дані векторного об'єкта, який у першому випадку інвенціонує в стек? Я думаю, це може бути "масив покажчика" (наприклад, класичний масив на C), що коли ви push_back елемент, векторний клас виділяє нову пам'ять на купу, а потім додає покажчик на цей масив покажчиків
додано Автор Karl, джерело
Я маю на увазі, якщо ви побудуєте вектор на купі за допомогою -> std :: vector * vector; <- Everythin це добре, цей "масив вказівника" буде перерозподілений, коли проміжок закінчиться .... але що це відбувається, коли ви будуєте свій вектор на стек? цей масив векторів буде створено на стекі замість купи, вірно? Редагувати: Звичайно, @uunchopanza, я не думав про ваш приклад ... це має сенс
додано Автор Karl, джерело

Векторний об'єкт може бути інстинктивним у стеку, але дані в межах вектора будуть на купі.

(Тривіальний клас class foo (int * data;); має цю характеристику)

6
додано
Насправді ваш тривіальний клас має вказівник на стек, якщо прикладення foo побудовано в стеку. Характеристика, яка є загальною для всіх декларацій змінних типу покажчика. Далі відображається навіть int * data; .
додано Автор Pixelchemist, джерело
Так, ви правильні, але те, що я роблю, полягає в тому, що пам'ять, до якої вказуються дані (можливо, належить). Вільно кажучи, це так, як працюють вектори STL.
додано Автор Bathsheba, джерело

Векторний об'єкт може бути інстинктивним у стеку, але дані в межах вектора будуть на купі.

(Тривіальний клас class foo (int * data;); має цю характеристику)

6
додано
Насправді ваш тривіальний клас має вказівник на стек, якщо прикладення foo побудовано в стеку. Характеристика, яка є загальною для всіх декларацій змінних типу покажчика. Далі відображається навіть int * data; .
додано Автор Pixelchemist, джерело
Так, ви правильні, але те, що я роблю, полягає в тому, що пам'ять, до якої вказуються дані (можливо, належить). Вільно кажучи, це так, як працюють вектори STL.
додано Автор Bathsheba, джерело

Ви по суті задаєте питання про деталі реалізації vector . Стандарт C ++ не визначає як вводити вектора , він лише визначає, що слід зробити vector та які операції потрібні для бути реалізованим. Ніхто не може точно сказати тобі, що трапляється при перерозподілі vector , оскільки кожен компілятор теоретично відрізняється.

При цьому неважко зрозуміти, як vector виконується зазвичай . Сам вектор є просто структурою даних, яка має вказівник на фактичні дані, що зберігаються у "в" векторі . Щось подібне:

template  class vector
{
public:
  void push_back (const Val& val);
private:
  Val* mData;
}

Вище це, очевидно, псудокод, але ви отримуєте ідею. Коли в стек (або на купі) виділяється vector :

vector v;
v.push_back (42);

Пам'ять може виглядати так:

+=======+        
| v     |
+=======+       +=======+
| mData | --->  |  42   |
+=======+       +=======+

Коли ви push_back до повного вектора, дані будуть перерозподілені:

+=======+        
| v     |
+=======+       +=======+
| mData | --->  |  42   |
+=======+       +-------+
                |  43   |
                +-------+
                |  44   |
                +-------+
                |  45   |
                +=======+

... і покажчик вектору до нових даних тепер вказується там.

3
додано

Вектор не масив елементів або пам'ять, яка використовується для зберігання таких елементів.

Вектор керує масивом елементів, пам'ять, для якої вона виділяє, виділяє, стискає і зростає, як потрібно.

Ваш вибір того, як ви виділяєте сам вектор, має відсутність з'єднання з власними рішеннями вектора про те, як і де виділити для неї керовану пам'ять.

Я не хочу перешкоджати вашої зацікавленості в роботі внутрішнього вектора (це цікаво і корисно), але ... цілком важливо написати класи та документувати їх, що ви потребуєте зрозуміти інтерфейс, а не реалізація.

1
додано
Дякую! Ваша відповідь доповнила коментар @ juanchopanza. І так, я погоджуюсь, що весь сенс написання класів та документування - зосередитись на інтерфейсі. Однак, я думаю, що потрібно мати принаймні туманне уявлення про те, як клас реалізується, щоб вміти писати хороший код і передбачити можливі помилки: немає гоблінів, що роблять брудну роботу з розподілом пам'яті!
додано Автор Karl, джерело

Вектор не масив елементів або пам'ять, яка використовується для зберігання таких елементів.

Вектор керує масивом елементів, пам'ять, для якої вона виділяє, виділяє, стискає і зростає, як потрібно.

Ваш вибір того, як ви виділяєте сам вектор, має відсутність з'єднання з власними рішеннями вектора про те, як і де виділити для неї керовану пам'ять.

Я не хочу перешкоджати вашої зацікавленості в роботі внутрішнього вектора (це цікаво і корисно), але ... цілком важливо написати класи та документувати їх, що ви потребуєте зрозуміти інтерфейс, а не реалізація.

1
додано
Дякую! Ваша відповідь доповнила коментар @ juanchopanza. І так, я погоджуюсь, що весь сенс написання класів та документування - зосередитись на інтерфейсі. Однак, я думаю, що потрібно мати принаймні туманне уявлення про те, як клас реалізується, щоб вміти писати хороший код і передбачити можливі помилки: немає гоблінів, що роблять брудну роботу з розподілом пам'яті!
додано Автор Karl, джерело

ви також можете зарезервувати резерв передбачуваного розміру,

vect.reserve(10000);

це буде зарезервувати 10000 об'єктів простору використовуваного типу

1
додано
IT KPI C/С++ новым годом
IT KPI C/С++ новым годом
747 учасників

Чат обсуждения С/С++. - Вопросы "напишите за меня лабу" - это оффтоп. - Оффтоп, флуд, оскорбления и вбросы здесь не приняты. - За нарушение - предупреждение или mute на неделю. - За спам и рекламу - ban. Все чаты IT KPI: https://t.me/itkpi/1147