Understanding how Vectors work in C++ (Part-1): How does push_back work?
This blog is focused to explain how vectors work in the backend, and we’ll specially look at push_back method of the vector container. Looking at the source code helps to understand the implementation, and how vectors can be used efficiently.
Vector Containers are type of sequenced containers in C++ commonly uses as a better alternative of arrays. They are also known as dynamic arrays, and as the term suggests — it’s one of the advantages they hold over native arrays in C++. You might have heard of Standard Library containers like vector , set , queue , priority_queue before. They all implement methods defined by the Container Concept.
A few important notes before we start:
- I’m using GCC 10.0.1 which is in the development stage. I’ve built GCC 10.0.1 from source on my local system. But everything I discuss here, should be same with GCC 8.4 or GCC 9.3 releases.
- I assume you are at least using C++11. If for any reason you are using C++98, there might be a few differences (for example, variadic arguments were not present in C++98). To not include lots of macros to check C++ versions, I’ve at times assumed the reader is using C++11 or greater.
- This blog uses lots of C++ Design Patterns that many would not be aware of. I understand it might just be a good idea to explain them first in a blog, but for now — I assume you have at least heard of them and know a thing or two about C++. I’ll cover these in future.
Let’s start with a basic comparison of using arrays and vectors in C++:
We can do the same (from what you see above) using vector :
While both do the same, but there are many important differences that happen in the backend. Let’s start with performance.
- The piece of code using vector containers in C++ took 23.834 microseconds.
- The piece of code using arrays in C++ took 3.26 microseconds.
If we had to do this for 10k numbers, the performance might be significant:
- The piece of code using vector containers in C++ (for 10k numbers) took 713 microseconds.
- The piece of code using arrays in C++ took 173 microseconds.
As in software development, there is always a tradeoff. Since vectors aim to provide dynamic memory allocation, they lose some performance while trying to push_back elements in the vectors since the memory is not allocated before. This can be constant if memory is allocated before.
Let’s try to infer this from the source code of vector container. The signature of a vector container looks like this:
Where _Tp is the type of element, and _Alloc is the allocator type (defaults to std::allocator<_Tp> ). Let’s start from the constructor of vector (when no parameter is passed):
The constructor when called with no params, creates a vector with no elements. As always, there are various ways to initialize a vector object.
I want to focus more on push_back today, so let’s take a look at it’s signature. It’s located in stl_vector.h file.
A few notes to take:
value_type : This is the type of the elements in the vector container. That is, if the vector is std::vector<std::vector<int> > , then value_type of the given vector will be std::vector<int> . This comes handy later for type checking and more.
_GLIBCXX_ASAN_ANNOTATE_GROW(1) : The definition of this macro is:
- The base struct _Vector_base defines these functions and structs. Let’s take a look at struct _Asan . Essentially, all we want to do with the above macro is to grow the vector container memory by n. Since when we insert an element, we only need to grow by 1, so we pass 1 to the macro call.
If usage of Macros is new to you, please leave it for now as we’ll discuss more about these design patterns in future.
A note on usage of _M_impl . It is declared as: _Vector_impl& _M_impl in the header file. _Vector_impl is a struct defined as:
The base struct _Vector_impl_data gives you helpful pointers to access later on:
To go deep into the details is not useful here, but as you would have sensed, this helps us to access pointer to the start, finish and end of storage of the vector.
You would have guessed by now, that push_back call will add the element to the end (observe _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x); ) and will then increment the variable _M_finish by 1.
Note how push_back first checks if there is memory available. Of course we have limited memory available with us, and it checks if the end location of the current vector container equals the end storage capacity:
So if we have reached the end of storage, it calls _M_realloc_insert(end(), __x) . Now what is this? Let’s take a look at it’s definition:
Even though the above piece of code might scare a few (it did scare me when I looked at it for the first time), but just saying — this is just 10% of the definition of _M_realloc_insert .
If you haven’t noticed so far, there is something very puzzling in the code: template<typename. _Args> – these are variadic arguments introduced in C++11. We’ll talk about them later in the series of blogs.
Intuitively, by calling _M_realloc_insert(end(), __x) all we are trying to do is reallocate memory (end_of_storage + 1), copy the original vector data to the new memory locations, add __x and deallocate (or destroy) the original memory in the heap. This also allows to keep vector to have contiguous memory allocation.
For today, I think we discussed a lot about vectors and their implementation in GCC. We’ll continue to cover rest of the details in the next part of the blog. I’m sure, the next time you plan to use push_back — you’ll know how things are happening in the backend. Till then, have fun and take care! 🙂
Добавить символ в конец строки в C++
В этой быстрой статье мы рассмотрим различные методы добавления символа в конец строки в C++.
1. Использование push_back() функция
Рекомендуемый подход заключается в использовании стандартного push_back() функция, которая перегружена для символов и добавляет символ в конец строки.
2. Использование += оператор
Мы также можем использовать string::operator+= , который перегружен для символов и внутренних вызовов push_back() функция.
3. Использование append() функция
Другим приемлемым подходом является использование append() функция для добавления одной копии символа в конец строки, как показано ниже:
4. Использование std::stringstream функция
Другой хорошей альтернативой является использование строкового потока для преобразования между строками и другими числовыми типами.
5. Использование insert() функция
Наконец, мы также можем использовать insert() Функция для вставки одной копии символа в указанную позицию в строке.
Это все о добавлении символа в конец строки в C++.
Оценить этот пост
Средний рейтинг 4.54 /5. Подсчет голосов: 80
Голосов пока нет! Будьте первым, кто оценит этот пост.
Сожалеем, что этот пост не оказался для вас полезным!
Расскажите, как мы можем улучшить этот пост?
Спасибо за чтение.
Пожалуйста, используйте наш онлайн-компилятор размещать код в комментариях, используя C, C++, Java, Python, JavaScript, C#, PHP и многие другие популярные языки программирования.
Как мы? Порекомендуйте нас своим друзьям и помогите нам расти. Удачного кодирования
Функция Vector Push_Back () в C++

Программирование и разработка
Динамический массив может быть реализован с использованием вектора в C ++. Добавлять элементы к вектору можно разными способами. Функция push_back () — это один из способов вставить новый элемент в конец вектора, который увеличивает размер вектора на 1. Эта функция полезна, когда требуется добавить один элемент к вектору. Если тип данных вектора не поддерживает значение, переданное аргументом этой функции, будет сгенерировано исключение, и данные не будут вставлены. В этом руководстве показан способ вставки данных в вектор с помощью функции push_back ().
Синтаксис:
Значение n будет вставлено в конец вектора, если тип данных вектора поддерживает тип данных n. Он ничего не возвращает.
Предварительные условия:
Прежде чем проверять примеры этого руководства, вы должны проверить, установлен ли компилятор g ++ в системе. Если вы используете Visual Studio Code, установите необходимые расширения для компиляции исходного кода C ++ и создания исполняемого кода. Здесь приложение Visual Studio Code было использовано для компиляции и выполнения кода C ++. Различные варианты использования функции push_back () для вставки элемента (ов) в вектор показаны в следующей части этого руководства.
Пример 1: Добавление нескольких элементов в конец вектора
Создайте файл C ++ со следующим кодом для вставки нескольких элементов в конец вектора с помощью функции push_back (). В коде определен вектор из трех строковых значений. Функция push_back () вызывалась трижды для вставки трех элементов в конец вектора. Содержимое вектора будет напечатано до и после вставки элементов.
//Include necessary libraries
#include <iostream>
#include <vector>
using namespace std ;
int main ( )
<
//Declare a vector of string values
vector < string > birds = < «Gray Parrot» , «Diamond Dove» , «Cocktail» >;
cout << «The values of the vector before insert: \n « ;
//Iterate the vector using loop to print the values
for ( int i = 0 ; i < birds. size ( ) ; ++ i )
cout << birds [ i ] << » « ;
cout << « \n « ;
/*
Add three values at the end of the vectior
using push_back() function
*/
birds. push_back ( «Mayna» ) ;
birds. push_back ( «Budgies» ) ;
birds. push_back ( «Cockatoo» ) ;
cout << «The values of the vector after insert: \n « ;
//Iterate the vector using loop to print the values
for ( int i = 0 ; i < birds. size ( ) ; ++ i )
cout << birds [ i ] << » « ;
cout << « \n « ;
return 0 ;
>
Следующий вывод появится после выполнения вышеуказанного кода. Выходные данные показывают, что три новых элемента были вставлены в конец вектора.

Пример 2: Вставка значений в вектор путем ввода
Создайте файл C ++ со следующим кодом, чтобы вставить элемент в пустой вектор, принимая значения от пользователя и используя функцию push_back (). В коде объявлен пустой вектор целочисленного типа данных. Затем цикл for берет от пользователя 5 чисел и вставляет числа в вектор с помощью функции push_back (). После вставки содержимое вектора будет напечатано.
//Include necessary libraries
#include <iostream>
#include <vector>
using namespace std ;
int main ( )
<
//Declare an integer vector
vector < int > intVector ;
//Declare an integer number
int number ;
cout << «Enter 5 numbers: \n « ;
/*
Iterate the loop for 5 times to insert 5 integer values
into the vector using push_back() function
*/
for ( int i = 0 ; i < 5 ; i ++ ) <
cin >> number ;
intVector. push_back ( number ) ;
>
cout << «The values of the vector after insert: \n « ;
//Iterate the vector using loop to print the values
for ( int i = 0 ; i < intVector. size ( ) ; ++ i )
cout << intVector [ i ] << » « ;
cout << « \n « ;
return 0 ;
>
Следующий вывод появится после выполнения вышеуказанного кода. Выходные данные показывают, что пять чисел, взятых у пользователя, были вставлены в вектор.

Пример 3: вставка значений в вектор на основе определенного условия
Создайте файл C ++ со следующим кодом, чтобы вставить определенные числа из целочисленного массива в пустой вектор. В коде объявлен пустой вектор и массив из 10 целых чисел. Цикл for был использован для перебора каждого значения массива и вставки числа в вектор с помощью функции push_back (), если число меньше 30 или больше 60. Содержимое вектора будет напечатано с использованием display_vector () после вставки.
//Include necessary libraries
#include <iostream>
#include <vector>
using namespace std ;
//Display the vector
void display_vector ( vector < int > nums )
<
//Print the values of the vector using loop
for ( auto ele = nums. begin ( ) ; ele ! = nums. end ( ) ; ele ++ )
cout << * ele << » « ;
//Add new line
cout << « \n « ;
>
int main ( )
<
//Declare an integer vector
vector < int > intVector ;
//Declare an array of numbers
int myArray [ 10 ] = < 9 , 45 , 13 , 19 , 30 , 82 , 71 , 50 , 35 , 42 >;
/*
Iterate the loop to read each element of the array
and insert those values into the vector
which are less than 30 and greater than 60
using push_back() function
*/
for ( int i = 0 ; i < 10 ; i ++ ) <
if ( myArray [ i ] < 30 || myArray [ i ] > 60 )
intVector. push_back ( myArray [ i ] ) ;
>
cout << «The values of the vector after insert: « << endl ;
display_vector ( intVector ) ;
return 0 ;
>
Следующий вывод появится после выполнения вышеуказанного кода. Выходные данные показывают, что числа 9, 13, 19, 82 и 71 были вставлены в вектор.

Заключение
В C ++ существует множество функций для вставки данных в начало или конец или в любую конкретную позицию вектора, например push_front (), insert () и т. Д. Использование функции push_back () будет очищено после практики примеров, показанных в этом руководстве.
std::vector<T,Allocator>:: push_back
Appends the given element value to the end of the container.
If the new size() is greater than capacity() then all iterators and references (including the end() iterator) are invalidated. Otherwise only the end() iterator is invalidated.
Contents
[edit] Parameters
| value | — | the value of the element to append |
| Type requirements | ||
| — | ||
[edit] Return value
[edit] Complexity
[edit] Exceptions
If an exception is thrown (which can be due to Allocator::allocate() or element copy/move constructor/assignment), this function has no effect (strong exception guarantee).
If T ‘s move constructor is not noexcept and T is not CopyInsertable into *this , vector will use the throwing move constructor. If it throws, the guarantee is waived and the effects are unspecified.
Notes
Calling push_back will cause reallocation (when size ()+1 > capacity () ), so some implementations also throw std::length_error when push_back causes a reallocation that would exceed max_size (due to implicitly calling an equivalent of reserve ( size ()+1)) .