是否存在在连续内存中存储元素数组的STL容器,其中元素大小在运行时指定
Is there an STL container that stores an array of elements in contiguous memory where the element size is specified at runtime?
我试图创建看起来接近我的文件规范如何工作的容器。它类似于vector,但元素的类型由哈希表定义。
如果我知道编译时的类型,我可以这样写:
struct foo {
float a,b,c;
int d;
byte e,f;
};
std::vector<foo> foovector;
foovector.push_back(foo f);
在编译时我没有这个结构体。我只有一个架构,我从文件头。所有元素的大小相同,元素内的每一项的偏移量也相同。在添加任何元素之前,容器已经定义了哈希表。
typedef Toffset uint; //byte offset;
typedef Ttype uint; //enum of types
std::unordered_map<std::string, std::pair<Toffset,Ttype>> itemKey;
itemKey["a"] = 0;
itemKey["b"] = 4;
itemKey["c"] = 8;
itemKey["d"] = 12;
itemKey["e"] = 16;
itemKey["f"] = 17;
nstd::interleaved_vector superfoo(itemKey, 10); //hashtable, pre-allocation size
nstd::interleaved_vector::iterator myIterator;
myIteratorGlobal = superfoo.begin;
myIteratorA = superfoo["a"].begin;
myIteratorB = superfoo["b"].begin;
*myIteratorB = 2.0f;
*myIteratorGlobal["d"] = 512;
这个想法是我可以快速记忆原始数据进出文件。迭代器偏移很容易。我的问题是:
有什么东西已经做到了吗?
这是个坏主意吗?我应该创建一个矢量,然后新建每个元素吗?我希望有数百万个元素。foo的大小范围是20到200字节
这是个坏主意?我应该创建一个耦合向量,每个元素一个?
还是这个"interleaved_vector"很好地解决了我的问题?
号是否存在一个STL容器来存储数组中的元素在运行时指定元素大小的连续内存?
你要求的看起来像是内存池的特定实现。也许是Boost。池库或其他实现对您有用吗?如果你习惯于使用原始内存和c++特有的对象创建/销毁,那么编写自己的对象应该不难。
:
有什么东西已经这样做了吗?
对我来说,这个想法看起来像一个内存池。内存池有很多种,所以你想要的实现完全取决于你的具体需求。
这是个坏主意吗?我应该创建一个矢量并分别新建吗元素?我希望有数百万个元素。的大小范围Foo将是20到200字节。
如果你想限制内存碎片,这是个不错的主意。池通常用于解决这个问题和其他与内存组织相关的问题。
例如,这在电子游戏中非常常见,主要是在主机上,但如果你需要高性能或大量内存,也可以在PC上。
如果你正在制作一个原型,或者你没有大量的数据需要分配,我不建议你这么做。如果您这样做,那么也许首先实现隐藏在工厂后面的最简单的分配(带有vector和new)会很好,并且允许您通过使用池来替换工厂实现。这样你就可以先检查一切是否正常,然后再优化。
给定以下代码:
typedef Toffset uint; //byte offset;
typedef Ttype uint; //enum of types
typedef std::pair<Toffset,Ttype> member;
typedef std::unordered_map<std::string, member> memberdefs;
memberdefs itemKey;
itemKey["a"] = member(0, 0);
itemKey["b"] = member(4, 1);
itemKey["c"] = member(8, 2);
itemKey["d"] = member(12,1);
itemKey["e"] = member(16,3);
itemKey["f"] = member(17,2);
可以读入char*缓冲区,并使用简单的包装器类。仍然容易出现bug,并且非常令人困惑。这个演示没有迭代器(尽管这很简单),并且需要一个外部缓冲区至少在类的作用域中停留一样长的时间。
class interleaved_vector {
const char* buffer;
size_t count;
size_t size;
std::shared_ptr<memberdefs> members;
public:
class dynamic_object {
const char* buffer;
std::shared_ptr<memberdefs> members;
friend interleaved_vector;
dynamic_object(const char* buffer_, std::shared_ptr<memberdefs> members_)
:buffer(buffer_), members(members_)
{}
dynamic_object& operator=(const dynamic_object& b) = delete;
public:
dynamic_object(const dynamic_object& b)
:buffer(b.buffer), members(b.members)
{}
template <class T>
T get(const std::string& member) const {
assert((*members)[member].second > 0); //no new members, requires pos sizes
assert((*members)[member].second == sizeof(T));
return *reinterpret_cast<T*>(buffer+(*members)[member].first); //technically undefined I think
};
template <>
T* get<T*>(const std::string& member) const {
assert((*members)[member].second > 0); //no new members, requires pos sizes
assert((*members)[member].second == sizeof(T));
return reinterpret_cast<T*>(buffer+(*members)[member].first); //technically undefined I think
};
void* operator[](const std::string& member) const {
assert((*members)[member].second > 0); //no new members, requires pos sizes
assert((*members)[member].second == sizeof(T));
return reinterpret_cast<void*>(buffer+(*members)[member].first); //technically undefined I think
};
};
interleaved_vector(const char* buffer_, size_t count_, size_t size_, const memberdefs& members_)
:buffer(buffer_), count(count_), size(size_), members(members_)
{}
dynamic_object get(size_t index) const {
assert(index<count);
return dynamic_object(buffer + size*index, members);
}
dynamic_object operator[](size_t index) const {
assert(index<count);
return dynamic_object(buffer + size*index, members);
}
size_t size() {
return count;
}
};
允许这样的代码:
size_t element_size = 32;
size_t num_elements = 1000000
char * buffer = new char[num_elements*element_size];
/*read into buffer*/
interleaved_vector iv(buffer, num_elements, element_size , members);
/*interleaved_vector DOES NOT COPY BUFFER. BUFFER MUST REMAIN IN SCOPE*/
for(int i=0; i<iv.size(); ++i) {
for(memberdefs::const_iterator j=members.begin(); j!=members.end(); ++j) {
dynamic_object ob = iv[i];
std::cout << "data[" << i << "]." << j.first << " = ";
std::cout << ob.get<int>(j.first) << 'n';
}
}
这个演示代码假设所有成员都是int型(get),但希望你能明白这是什么意思
您可以编写自己的类,但这将是一个非常痛苦的过程。最好使用vector(或boost::ptr_vector),它不需要您做任何努力,并且对于每个程序员来说都很容易读懂。
- CMake-按正确顺序将项目与C运行时对象文件链接
- 我在c++代码中生成了一个运行时#3异常
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- Leetcode 540 上的运行时错误.排序数组中的单个元素
- 动态分配数组中的运行时错误,用于删除 C++ 中的元素
- 在运行时基于基础元组类型生成元素
- 在运行时按索引访问 std::tuple 元素的最佳方法
- 在运行时C++将元素插入到向量中.引发运行时错误
- void * 到 std::tuple 在运行时的第 n 个元素
- 如何在运行时在boost::fusion::vector中查找元素
- 从具有O(1)运行时的向量中移除元素
- 如何在C++中的运行时获得给定元素的模板类型
- 运行时来自元组的源模板函数元素
- 访问矢量容器的元素时发生运行时错误
- 在c++中,当元组的元素索引在运行时已知时,是否有可能获得该元素的类型?
- 是否存在在连续内存中存储元素数组的STL容器,其中元素大小在运行时指定
- Linux中的c++运行时错误::glibc检测到free():无效的下一个大小(快速):堆栈具有void ptr元素
- 为什么如果 QWidget 在屏幕上不可见,我只能在运行时向 QWidget 添加元素?
- 为什么在C++中访问过去时结束元素时没有运行时错误
- 为什么当我访问数组的越界元素时没有收到运行时错误?