查找自动生成键并具有线性内存消耗的小型关联数组

looking for small associated array where key is automatic generated and has linear memory consumption

本文关键字:小型 数组 关联 内存 线性 自动生成 查找      更新时间:2023-10-16

就像标题所说,我正在寻找一个具有线性内存消耗的关联数组(如地图((如 std::vector(,其中键是为新条目自动生成的。N <128。

例如,我们可以将其用于观察者模式,如果您可以将回调注册到值更改事件。作为回报,您将获得一个 id(整数(。使用此 ID,您可以稍后取消注册回调。

别名代码:

/// Registers a callback and returns an associated id to it.
int register_callback(std::function callback);
/// Returns true if callback was unregistered for given id.
bool unregister_callback(int id);

由于这应该在有内存限制的嵌入式设备中使用,所以我不会使用映射作为容器(请参阅此处:http://jsteemann.github.io/blog/2016/06/14/how-much-memory-does-an-stl-container-use/,映射使用的内存是矢量的 ~5 倍(。

我有一些想法如何自己实现这一点,但我想知道是否已经存在任何名称/概念?

这将是我的想法:

template<typename T>
class custom_map { // Totally unsure with naming
// coll_ is sorted.
std::vector<std::pair<uint8_t, T>> coll_;
public:
uint8_t add(T) {
// Find unused id by iterating over coll_,
// If ((prev id + 1) != (next id)), free id found. 
// Insert into coll new pair and sort.
}
bool remove(uint8_t id) {
// Remove element in coll with associated id 
// Binary search would be faster but only for bigger sizes, so linear search?
}
// Iterator concept begin/end... to iterate over collection.
};

您不需要在对象中保存单独的 id。您可以使用向量的索引作为 id。那会快得多。

template<typename T>
class custom_map { // Totally unsure with naming
std::vector<T*> coll_;
public:
uint8_t add(T*obj) {
// Find unused id by iterating over coll_,
for (int i = 0; i < coll_.size(); ++i) {
if (coll_[i] == nullptr) {
coll_[i] = obj;
return i;
}
}
coll_.push_back(obj);
return coll_.size() - 1;
}
bool remove(uint8_t id) {
coll_[id] = nullptr;
}
// Iterator concept begin/end... to iterate over collection.
};

您可能使问题过于复杂,您可以简单地使用向量的索引作为键:

#include <vector>
#include <cstdint>
#include <functional>
#include <iostream>
template<typename T>
class custom_map {
std::vector<T> coll_;
public:
size_t add(const T& t) {
for (auto it = coll_.begin(); it != coll_.end(); ++it)
{
if (!(*it))
{
*it = t;
return it - coll_.begin();
}
}
coll_.push_back(t);
return coll_.size() - 1;
}
bool remove(size_t id) {
if (id >= coll_.size() || !coll_[id]) {
return false;
}
coll_[id] = {};
// remove empty elements from the end of the list
if (id == coll_.size()-1) {
auto toRemove = std::count_if(coll_.rbegin(), coll_.rend(), [](const T& t) { return !t; });
coll_.resize(coll_.size() - toRemove);
}
return true;
}
};
int main()
{
custom_map<std::function<void()>> map;
auto i = map.add([](){std::cout << "1n"; });
map.remove(i);
}

这仅适用于默认初始化为可转换为 false 的值的类型(如std::function(,对于其他类型,您只需将类型包装在std::optional中,例如(映射实际上也适用于int,但0空值可能不是您想要的(:

int main()
{
custom_map<std::optional<int>> map;
auto i = map.add(10);
map.remove(i);
}