我正在构建一个玩具虚拟机,它需要一块内存来存储和访问不同类型和不同大小的数据元素。我已经通过在所需大小的uint8_t *数据块周围编写包装类来完成此操作。该类具有一些模板方法,用于向/从内存块中的任意位置写入/读取类型化数据元素,两者都检查以确保不违反边界。这些方法使用memmove,我希望这是一种或多或少安全的方式。也就是说,虽然我愿意朝着这个方向努力,但我必须相信其他拥有更多专业知识的人曾经在这里,可能愿意分享他们的智慧。特别是:
1)是否有一个C ++标准(过去,现在,将来)中的一个类被定义为执行类似于我上面概述的功能?
2)如果没有,那里有一个(最好像啤酒一样免费)库吗?
3)除此之外,除了边界检查和将一种类型写入内存位置并阅读与该位置不同的不可避免的问题之外,我还应该注意其他问题吗?
修改
这是我正在尝试做的简化(即析构函数和其他一些相关方法);但它抓住了它的本质:
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <iostream>
class block
{
private:
uint8_t *data;
size_t size;
protected:
block(const void* src, size_t size)
: data(new uint8_t[size]), size(size) { ::memmove(data, src, size); }
void set(const void* src, size_t dst_adr, size_t len)
{
assert( (size > dst_adr) && (size > len) && ( (size - len) > dst_adr) );
::memmove(data+dst_adr, src, len);
}
void* get(size_t src_adr) const
{
assert( size > src_adr );
return data+src_adr;
}
public:
block(size_t size) : data(new uint8_t[size]), size(size) {}
size_t get_size() const { return this->size; }
virtual void copy(const block& src, size_t src_adr, size_t dst_adr, size_t len)
{
// Bounds check
assert( (size > dst_adr) && (size >= len) && ( (size - len) >= dst_adr) );
assert( (src.size > src_adr) && (src.size >= len) && ( (src.size - len) >= src_adr) );
::memmove(data+dst_adr, src.data+src_adr, len);
}
};
template <typename T>
class typed_block : public block
{
public:
typed_block(const T& val) : block(&val, sizeof(T)) {}
// Could use reinterpret_cast here instead, per Ben Voigt below
operator T () const { return *((T*) this->get(0)); }
typed_block<T>& operator=(const T& val)
{
this->set(*val, 0, get_size());
return *this;
}
};
int main(int argc, char** argv)
{
block db(512);
typed_block<long> x(1 << 30);
typed_block<short> y(0);
db.copy(x, 0, 15, x.get_size());
y.copy(db, 17, 0, y.get_size());
std::cout << "x = " << x << "\ty = " << y << std::endl;
return 0;
}
所以,我想我真正得到的是,是否有可用的类库(在任何C ++标准之内或之外),它们基本上提供了这种功能。我想让我感到不舒服的是在块类中传递“void *”参数(即使是受保护的成员),我正在寻找一种更安全的方法来执行此操作。
感谢
- &安培;。&安培;
答案 0 :(得分:5)
嗯,因为你使用的是C ++,听起来好像在寻找STL allocator
和/或placement new
。
答案 1 :(得分:1)
有reinterpret_cast
,但它需要正确对齐,memmove
没有。
答案 2 :(得分:1)
如果你分配一个boost::variant的数组,那么你可以在每个位置允许多种不同的类型;但是,每个元素分配的空间量将等于所有可能类型的最大值。但请注意,如果您只使用基本类型和void *,那么这不会浪费那么多空间。