All the literature (both on-line and textbooks) I referenced to learn how to use STL containers only showed how to use them to hold primitives, (e.g. integers, strings, etc.), and made no mention of how to handle objects or struct
s.
This C++ Pointer
shows you how to manipulate objects and struct
s stored in an STL Vector and an STL Map. There are other STL containers, but once the use of these two containers is known the same techniques can be used for the others.
The first version of this code was written around 2005, in 2023 I updated the code to use C++11, C++14 and C++17 updates. The following updates have been made;
.push_back
has been replaced with .emplace_back
and for STL Map .insert
has been replaced with .emplace
. try_emplace
isn't supported by my compiler.std::unique_ptr
to prevent memory leaksfind_if
to find an object or classauto
std::pair<key, value>
, instead of itr->first
and itr->second
std::endl
which causes the buffer to be flushedTo make the example relatable and easily understandable and focus on the code required for using the STL container, rather than the application, the example code uses a simple Class (ColourCode.cpp) and struct
(ColourCodeStruct) that contain the name of a colour and its Red, Green and Blue colour values. Consequently, the use cases are very simple, but make it easier to focus on how to use an object or struct
stored in an STL container.
How to use this object and struct
in an STL Vector is shown in VectorExample.cpp and in MapExample.cpp for an STL Map.
The example programs have identical functionality. A container to hold the ColourCode objects and another to hold the struct
s are created and then passed by reference to an object of Loader. This loads the containers with ColourCode objects and struct
s that contain the colour information for the basic web browser colours.
Iterators for the containers are created and are used to step through the contents of the container. For each object and struct
in the container details of the object and struct
are extracted and written to a file, (VectorExample_res.txt or MapExample_res.txt). Then the colour named custom1 is located in the container and its properties modified to khaki. The contents of the container are then written to the file.
This C++ Pointer
assumes you know how to use a Vector or Map to hold primitives, as this is widely described in literature. If you want to know how to use the STL Vector or Map check out www.cppreference.com/cppstl.html or Google etc., for information on the Standard Template Library.
C++ Pointeris distributed with
struct
sA Vector or Map of objects is created in the same way that a Vector or Map of primitives is created. An example of the simplest manner in which they are created is as follows;
The creation of a Vector or Map of struct
s follows the same format,
struct
to an STL VectorThe emplace_back
function enables the creation of a object or struct
in place, rather than using a create and copy. Because I often work with loading variable length data I like to add an empty object and then load data into it, rather than loading all the data and creating the object, which results in the last object having to be added outside the data import loop. Having to add the last object outside the data import loop means extending the object's lifespan and makes code maintainence harder if there is additional work in the application when an object is created.
In the following example on how to add an object or struct
I create add an empty object and then get an iterator to it, and update the newly added object. Of course, if you want to add a "full" object, then there is no need to create the iterator.
In the example above args are any arguments you want to forward for the construction of the object.
As the iterator returned is to a std::unique_ptr<object>
or std::unique_ptr<struct>
we have to get()
the contained pointer to the actual object or struct
.
struct
to an STL MapFor Map I use the emplace
function to create the object or struct
in place, for the same reasons described above for the Vector. In the following example on how to add an object or struct
I create add an empty object and then get an iterator to it, and update the newly added object. Of course, if you want to add a fully constructed object, then there is no need to create the iterator. Even if you create the object in place you may still want to "get" the return value to test if the object or struct
was added, or if it was not.
In the example below, insertedElement
is a std::pair<std::pair< key, iterator>, bool>
, where key is the key referencing the inserted element, iterator is an iterator referencing the inserted element, and bool is true if the insertion happened, and false if it did not.
You can also use std::make_pair
to create the key and object or struct
pair to be added to the Map, see the file Loader.cpp.
struct
sAn Iterator for a Vector or Map of objects or struct
s is created the same way as if it was being created for a Vector or Map of primitives, for example,
However the addition of type deduction, (auto
) to the language simplifies iterator creation.
struct
Stored in an STL VectorAn object or struct
can be found in an STL Vector using the STL algorithm find_if, the same way that it would be used for a Vector of primatives.
Note, in my code I'm using std::unique_ptr<
>s, so need to use std::unique_ptr.get()
to access the managed object or struct
, for example,returned_iterator->get()->member_function
.
To access the member functions of an object in a Vector you create an Iterator to the Vector, (cCOItr in this example) and then treat the iterator as a pointer to the object and use the -> (structure pointer dereference) operator in place of the dot operator to access the object's member function. For example;
struct
stored in an STL VectorTo access the elements of a struct
in a Vector you create an Iterator to the Vector, (cCSItr in this example) and then treat the iterator as a pointer to the struct
and use the -> (structure pointer dereference) operator as normal. For example;
An object in a Vector can be passed into a function that takes a reference to the object, by dereferencing the iterator (cCOItr in this example). For example;
Note, in the function the object referenced by the iterator is now treated as if it is an object so the member functions are referenced using the . (dot) operator.
To access the member function of an object in a Map you create an Iterator to the Map, (cCOItr in this example) and use it to select the object you are interested in as applicable. Use the -> (arrow) (structure pointer dereference) operator to access the object which is the second parameter of the iterator and then use dot notation to access the object's member function as follows;
Note, in my code I'm using std::unique_ptr<
>s, so need to use std::unique_ptr.get()
to access the managed object.
From C++ 17 auto
can be used to create a std::pair<Key, Element>
iterator and we can use Key and Element rather than ->first and ->second, for example
struct
Stored in an STL MapTo access the elements of a struct
in a Map you create an Iterator to the Map, (cCSItr in this example) and use it to select the struct
you are interested in as applicable. Use the -> (structure pointer dereference) operator to access the struct
which is the second parameter of the iterator and then use dot notation to access the element of the struct
. For example;
Note, in my code I'm using std::unique_ptr<
>s, so need to use std::unique_ptr.get()
to access the managed struct
.
From C++ 17 auto
can be used to create a std::pair<Key, Element>
iterator and we can use Key and Element rather than ->first and ->second, for example
An object in a Map can be passed into a function that either;
takes the reference of a Map Iterator, which you can do if you also want the value of the Map Key, for example;
Note, in my code I'm using std::unique_ptr<
>s, so need to use std::unique_ptr.get()
to access the managed object.
Note, because we are passing an iterator into the iterator reference parameter of the function, the iterator is not dereferenced in the function call, and within the function the variable is an iterator and the first and second parameters of the iterator are referenced with the -> (arrow) (pointer dereference) operator.
Or, if you only want the object, the second parameter of the Map iterator can be passed into a function that takes a reference to the object, for example;
Note, in the function the object referenced by the iterator is now treated as if it is an object so the member functions are referenced using the . (dot) operator.
This C++ Pointer
was compiled and tested using Apple clang version 14.0.0 on x86_64-apple-darwin22.3.0 and with Windows 10 using cygwin-3.2.0, gcc version 10.2.0
To obtain the source code, install and execute this C++ Pointer
use the following procedure.
CppPtr1
and place the source files in itCppPtr1
folderVectorExample.cpp
and MapExample.cpp
which contain the code to demonstrate using objects and structs in a Vector and a Map respectivelyIf you suspect a bug please e-mail a description being sure to identify that the bug report is about C++ Pointer #1 and include as much detail as possible.