std::vector
#include <iostream>
int main()
{
std::cout << "Hi, I'm Borislav!\n";
std::cout << "These slides are here: https://is.gd/beyondvec\n";
return 0;
}
A blog post of what we do: ibob.bg/blog
Popular in multi-platform software and game development
std::string_view
arrived in C++17std::span
arrived in C++20.map/set
of string pre-C++14 is uselessunordered_map/set
of string pre-C++20 is uselessiostream
: a notoriously bad offenderflat_map/set
in contiguous memorystd::hash
(this is a documented extension point)map
, set
, list
allocate every nodeunoredered_map/set
also allocate every nodefunction
sizeof std::<pretty-much-anything>
std::string
sizestd::filesystem::path::c_str()
returns whateversize_t
std::move_if_noexcept
The Great Dividerstd::function
must be copyablestd::map::map
is not noexcept
...usually
std::vector
std::vector
std::vector
std::reference_wrapper
const std::vector
my::vector
A 100% compatible drop-in replacement reimplementation
shrink_to_fit
is not required to shrinkemplace
returns a ref since C++17noexcept
move since C++17std::move_if_noexcept
std::move_if_noexcept
DramaSpeaking of immutable objects
Think std::string_view
You don't change. You copy.
template <typename T>
class ivector {
std::vector<T> m_vector;
// ...
ivector erase(const_iterator i) {
auto offset = i - begin();
auto copy = m_vector;
copy.erase(copy.begin() + offset);
return {copy};
}
};
We copied the erased item as well
We allocated more memory
template <typename T>
class ivector {
std::vector<T> m_vector;
// ...
ivector erase(const_iterator i) {
auto offset = i - begin();
std::vector<T> copy;
copy.reserve(m_vector.size() - 1);
copy.insert(copy.end(), m_vector.begin(), i);
copy.insert(copy.end(), i+1, m_vector.end());
return {copy};
}
};
gh/arximboldi/immer - immutable container library
I've been quite into immutable objects for the past two years.
Let's chat!
Most std::vector
alternatives are there to deal with allocations.
So, what about them?
Rule of thumb: Always Avoid Allocations!
... unless you really know what you're doingstd::pmr
helps, but not muchstd::pmr
is not zero costI'm not against std::pmr
Use std::pmr
as much as possible!
Sometimes you can completely avoid allocations
What if the size is always smaller than a given N?
std::array
?
std::array
static_vector
static_vector
boost::static_vector
- a powerful implementationitlib::static_vector
std::move_if_noexcept
at
Can we have the best of all worlds?
small_vector
small_vector
boost::small_vector
- a poweful implementationitlib::small_vector
std::move_if_noexcept
at
What if the size is absolutely random?
std::vector
?
realloc
We have a block of memory:
_expand
(Windows only)We have a block of memory (on Windows):
std::vector
and realloc
memcpy
disregards constructors and destructors_expand
can actually work_expand
can be implemented for any allocatorallocate_at_least
is a poor attempt to helppod_vector
itlib::pod_vector
realloc
, memcpy
, memmove
..._expand
if availableat
optimal_alloc_vector
: uses _expand
uber_vector
: can be any of thesestd::vector
is still quite powerfulstd::pmr::vector
is awesomeWe have a bajillion vector types. How do we write an algorithm?
void work(const std::vector<obj>& data);
doesn't work anymore
Templates, of course work, but at a cost.
And don't get me started on ranges!
How about
void work(const obj* buf, size_t size);
The answer is yes!
std::span
std::span
... not even C++11
my::span
std::span
boost::span
itlib::span
But what about ranges?
But that's just, like, my opinion, man
ufunction
- capture non-copyable (like unique_ptr
)flat_map, flat_set
- map with cache localitysentry
- finally-type blocksBorislav Stanimirov / ibob.bg / @stanimirovb
These slides: ibob.bg/slides/beyond-vec/
Demo code: github.com/iboB/vec-span-demo
Slides license Creative Commons By 4.0