Initializing a std::map when the size is known in advance

std::map example
std::map insert
initialize map c++
how to initialize map in c++ with 0
c++ map insert if not exists
hashmap c++
map size c++
c 11 std map initialize

I would like to initialize a std::map. For now I am using ::insert but I feel I am wasting some computational time since I already know the size I want to allocate. Is there a way to allocate a fixed size map and then fill the map ?

No, the members of the map are internally stored in a tree structure. There is no way to build the tree until you know the keys and values that are to be stored.

std::map, and you have no idea when it gets used first but you want to assure that the values are available in it. std::map and std::multimap both keep their elements sorted according to the ascending order of keys. In case of std::multimap, no sorting occurs for the values of the same key. The basic difference between std::map and std::multimap is that the std::map one does not allow duplicate values for the same key where std::multimap does.

The short answer is: yes, this is possible, but it's not trivial. You need to define a custom allocator for your map. The basic idea is that your custom allocator will set aside a single block of memory for the map. As the map requires new nodes, the allocator will simply assign them addresses within the pre-allocated block. Something like this:

std::map<KeyType, ValueType, std::less<KeyType>, MyAllocator> myMap;

myMap.get_allocator().reserve( nodeSize * numberOfNodes );

There are a number of issues you'll have to deal with, however.

First, you don't really know the size of each map node or how many allocations the map will perform. These are internal implementation details. You can experiment to find out, but you can't assume that the results will hold across different compilers (or even future versions of the same compiler). Therefore, you shouldn't worry about allocating a "fixed" size map. Rather, your goal should be to reduce the number of allocations required to a handful.

Second, this strategy becomes quite a bit more complex if you want to support deletion.

Third, don't forget memory alignment issues. The pointers your allocator returns must be properly aligned for the various types of objects the memory will store.

All that being said, before you try this, make sure it's necessary. Memory allocation can be very expensive, but you still shouldn't assume that it's a problem for your program. Measure to find out. You should also consider alternative strategies that more naturally allow pre-allocation. For example, a sorted list or a std::unordered_map.

Java HashMap Inline Initialization, 3 Self-organizing Maps In this section, first the SOM algorithm [5] is briefly Initialize the learning rate parameter, neighborhood size and set the number of Ne(t) using the standard update rule [5]: wi(t + 1) = widt) + a(t)[a – wi(t)] where i e Ne(t). As the relational attributes have known dynamic ranges, it is not necessary to  36 Initializing a std::map when the size is known in advance Oct 24 '12 12 ReferenceError: Can't find variable: __fbBatchedBridge Jan 18 '16 10 Documenting google tests Aug 21 '12

Not sure if this answers your question, but Boost.Container has a flat_map in which you can reserve space. Basically you can see this as a sorted vector of (key, value) pairs. Tip: if you also know that your input is sorted, you can use insert with hint for maximal performance.

Initializing a static std::map<int, int> in C++, Mapping. Technique. for. Active. Initialization. of. the. Multilayer. Pcrccptron errors for a standard back-propagation with a random initialization (mean values of 10 lower generalization error and were less sensitive to network size and input  his post, we will how to initialize a map in C++. There are several approach to initialize a std::map or std::unordered_map in C++ as shown below: 1. Initializer List In C++11 and above, we can use initializer lists '{}' for initializing a map containers.

You are talking about block allocators. But it is hard to implement. Measure before think about such hard things. Anyway Boost has some articles about implementing block allocator. Or use already implemented preallocated map Stree

std::map thread-safety, Table 1: Training parameters of Standard SOM and MIL-SOM* algorithms Standard the new method (MIL-SOM*) for initialization and training the standard SOM. radius reached 1, where max is the maximum value of the map size matrix. map::size. Returns the number of elements present in the map. 37: map::swap. Exchanges the content of map with contents of map x. 38: map::upper_bound. Returns an iterator pointing to the first element which is greater than key k. 39: map::value_comp. Returns a function object that compares objects of type std::map::value_type.

There are several good answers to this question already, but they miss some primary points.

Initialize the map directly

The map knows the size up front if initialized directly with iterators:

auto mymap = std::map(it_begin, it_end);

This is the best way to dodge the issue. If you are agnostic about the implementation, the map can then know the size up front from the iterators and you moved the issue to the std:: implementation to worry about.

Alternatively use insert with iterators instead, that is:

mymap.insert(it_begin, it_end);

See: https://en.cppreference.com/w/cpp/container/map/insert

Beware of Premature optimization

but I feel I am wasting some computational time.

This sounds a lot like you are optimization prematurely (meaning you do not know where the bottleneck is - you are gueessing or seeing an issue that isn't really one). Instead, measure first and then do optimization - repeat if neccesary.

Memory allocation could already be optimized, to a large degree

Rolling your own block allocator for the map could be close to fruitless. On modern system(her I include OS/hardware and the c++ language level) memory allocation is already very well optimized for the generel case and you could be looking at little or no improvement if rolling your own block allocator. Even if you take a lot of care and get the map into one contiguoes array - while an improvement in itself - you could still be facing the problem that in the end, the elements could be placed randomly in the array (eg. insertion order) and be less cache friendly anyway (this very much depending on your actual use case though - Im assuming a super large data-set).

Use another container or third party map

If you are still facing this issue - the best approach is probably to use another container (eg. a sorted std::vector - use std::lower_bound for lookups) or use a third party map optimized for how you are using the map. A good example is flat_map from boost - see this answer.

Conclusion
  1. Let the std::map worry about the issue.
  2. When performance is the main issue: use a data structure (perhaps 3rd party) that best suits how your data is being used (random inserts or bulk inserts / mostly iteration or mostly lookups / etc.). You then need to profile and gather performance metrics to compare.

Advances in Self-Organising Maps, p. obj= new T(value); p. copy = &local_cast: : copy; p.del = &local_cast:: destroy; Some functions come for free on the top of std::map: size t size() const { return { initialized value&TX v; get(v.result, name); return v. result; } At this moment, you  Returns the number of elements in the map container. Parameters none Return Value The number of elements in the container. Member type size_type is an unsigned integral type.

Advances in Pattern Recognition: Joint IAPR International , Advanced Computer Subject, Advanced Data Structure, Algorithms, Algorithms Quiz, Analysis, AngularJS, Aptitude, Arrays, Articles Maps are associative containers that store elements in a mapped fashion. In C++, size() function is used to return the total number of elements present in the map. using namespace std;. If you know ahead what the size is, then you should initialize it so that memory is only allocated once. If you only have a rough idea of the size, then instead of allocating the storage as above, you can create the vector with the default constructor and then reserve an amount that is approximately correct; e.g.

Proceedings from the International Conference on Advances in , Advanced Computer Subject, Advanced Data Structure, Algorithms, Algorithms Quiz, Analysis Inserting elements in std::map (insert, emplace and operator []) Time complexity : log(n) where n is size of map; insert(hint, pair) : In this to key, default constructor is called and assigns a “null” or “empty” value to the key. Size  void printArray(const std::array<int, 5> &n) - const is used here to prevent the compiler from making a copy of the array and this enhances the performance. The passed array will be n in this function as &n is the parameter of the function 'printArray'.

Advanced Metaprogramming in Classic C++, std::map and std::multimap both can be initialized by providing key-value pairs it = mmp.begin(); std::advance(it,3); //moved cursor on first {6, 5} std::map< int,  So push_back should be used only when vector dimensions are not known in advance. 4. C++11 – Initializer Lists. Finally, we can use initializer lists to initialize a two-dimensional vector with given default value as shown below. Note this will only work with C++11 and above.

Comments
  • Why not use the iterator or initializer list version of insert? Do you know the number of elements ahead of time but not their values?
  • Yes I know the number but not the pairs key-values.
  • Is map::insert really the bottleneck in your program?
  • not possible without knowing keys
  • A great question to show the real nature of std::map. It's definitely more than "a kind of vector plus some magic".
  • At best, you could allocate all the nodes ahead of time.
  • @Mankarse: It wouldn't make much of a difference, since each node must be allocated (and deallocable) separately. There's really very little to be gained from advance knowledge of the contents of the map (unless it were completely constexpr).
  • @Mankarse: Doing that wouldn't save any time though. (Unlike with vector.reserve(), which does save time by avoiding much resizing and copying.)
  • You could create an exactly sized pool allocator, which would make the allocation of individual nodes significantly faster. For this to be really effective, however, you'd have to also know that the number of nodes will never change. If you know all this, it shouldn't be hard to write a custom allocator which would do the job.
  • This answer is borderline wrong - if you have eg. 100.000+ elements and you knew it up front - allocating everything in one contiguous array could dramaticly speed up processing.
  • I really agree with the last paragraph. Probably a sorted vector will be the most effective solution in this case.
  • Is there some hope for a standardised method for getting the node size or will we remain dependent on estimates?
  • I can't see that happening. If you look closely at the definition of std::map, you'll see that it doesn't even promise to be implemented as a tree.
  • The function get_alloc returns allocator_type (by value) which means that myMap.get_allocator().reserve( nodeSize * numberOfNodes ); calls reserve on a temporary MyAllocator instance. Furthermore, knowing the tree node size of a map implementation is irrelevent because the allocator is used to allocate objects of type std::pair<const Key, T> which means that you can perfectly know the size in advance.
  • This will depend on the map implementation, but I would expect most to combine both the key/value pair and related node info in a single object. In any case, if you want to do a single allocation for your map, then you must know both the size of the data you intend to store plus the map overhead. It is true that get_allocator() returns a copy, which can be a nasty gotcha. Whether myMap.get_allocator().reserve(...) does what you'd hope depends on the allocator implementation. This whole scenario actually gets much easier with the new polymorphic allocators in C++17.