c++ - 使用自定义分配器分配 std::vector 并且在运行时类型未知

标签 c++ vector memory-management

对于该问题,假设有以下代码流:

void * some_data = allocate_memory(const std::string & type)

fetch_data_from_somewhere(some_data);

send_data_to_client(some_data);

allocate_memory将只分配一个空消息,它将通过 fetch_data_from_somewhere 填充(包括可能进一步分配动态内存)然后通过 send_data_to_client 发送到某个地方.然后客户端将数据转换为真实类型(只有他自己知道)。

我现在必须将函数写入 allocate_memory仅给出一个标识类型的字符串。有了这些信息,我可以获得一个描述消息的数据结构(例如:它有 80 个字节长,前 4 个字节中有一个整数,之后是一个 std::vector,等等)。

假设我知道我必须分配一个 std::vector<T>其中 T是我不知道的类型(同样,我知道该类型的字符串标识符,并且可以访问有关其结构、大小等的信息)。

如果我使用 void * some_memory = calloc(sizeof(std::vector<T>), 1) ,这似乎对所有人都有效 T ( bool 值除外)与 gcc、clang 和 MSVC++ 编译器。稍后,客户可以做 static_cast<std::vector<T>>(some_memory)并且使用所有 vector 操作似乎都有效。这似乎有点合理,尽管我无法判断它是否一定能正常工作。

但是,如果我想传递我自己的分配器,在我看来我运气不好:我希望零分配内存不起作用,但我真的做不到 void * = new std::vector<T, MyAllocator>(0, my_allocator)或类似的,因为我不知道 T .如果我需要 std::vector<T *> 类型的 vector 相反,我假设可以只使用 std::vecotr<void *>因为无论如何数据在内存中都是未类型化的。

有没有办法分配std::vector<T, MyAllocator>未知类型 T在编译时(跨平台...)?

这显然不是预期用途,也不是干净的代码,但为了这个问题,让我们假设我对此无能为力。

最佳答案

只是分配一堆内存并不能生成 vector 。你的calloc解决方案是错误的,因为它实际上并没有构造一个 vector ,而且您构造它的内存没有正确对齐。您反复观察到此方法“有效”这一事实纯属倒霉;在理论上和实践中,您可以预期它会发生灾难性的爆炸。

即使您需要做的只是分配一些内存,您仍然无法使用未知类型的 vector 来完成它,因为您不知道 vector<unknown-type> 有多大。是。当然你不能 build 一个。甚至你的vector<T*>vector<void*>这个想法行不通:你忘记了每个 vector特化是一种完全不同的类型,值类型之间的关系不会在生成的容器类型之间创建关系。

您的方法太天真了,无法成功生成一般的 C++ 对象。 C++ 给我们 operator new 是有原因的和协调工作的分配器。 “提供内存,使用内存”的旧 C 风格方法是不够的。您随后想要“向客户端发送数据”这一事实也是一个危险信号:您不能通过将复杂的 C++ 对象的直接字节转储到网络来序列化它们。

最后,我必须警告 C++ 是一种抽象,如果您试图编写在字节级操作对象的“聪明”源代码,则需要非常小心。 C++ 希望您在创建对象时直接告诉它,在销毁该对象时直接告诉它;如果不这样做然后假装该对象存在很容易出现各种奇怪的情况,因为编译器(包括但不限于在优化阶段)充分利用了构成该语言的复杂的、高度语义化的规则。一般来说,你确实需要“告诉它你的意思”,而不是试图躲在它的背后。 (此规则存在一些有限的异常(exception)情况,主要是对内置类型对象的宽容,以及使用 char* 为现有的、正确构造的对象添加别名的能力;这些异常(exception)情况均不适用于您的要求。)

坚持使用提供的构造/分配工具,编写序列化器。

关于c++ - 使用自定义分配器分配 std::vector 并且在运行时类型未知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53122381/

相关文章:

c++ - 在运行时改变对象的行为

c++ - 在VS2010 C++中解析 "found ' {' at file scope (missing function header?)"

c++ - 在函数调用中包装 std::cout

java - Pragma Pack 使用 C 库导致 jvm 崩溃

c - 编程上下文中的虚拟地址空间

c++ - 删除外部类实例中的内部类实例

c++ - 如何调用矩阵调色板API

android - 在 Android Studio 中使用矢量进行错误渲染

OpenCV 存储点向量的向量 vector<vector<Point>>

c++ - 在 vector 中放置派生的可移动但不可复制会产生编译错误