"空" array \ vector members c ++

时间:2017-09-09 18:40:32

标签: c++ arrays object vector sentinel

我必须通过从磁盘读取数据来填充1000个对象的数组。但是,并非每个对象都会退出。

一旦我声明了一个数组,就会为1000个对象保留内存。 当我逐一阅读时,我将内存设置为相应的值。但是,成员#276可能没有对象,并且它的内存将保持设置为声明数组时的内容。

如何保留阵列中某些成员无效/不存在的信息?

我可以以某种方式将成员的所有字节设置为零,但这可能是一个有效的对象。

显而易见的解决方案是添加另一个字节数组,这些数组将设置为1或0,具体取决于该索引处的对象是否存在,但它看起来并不优雅。

这可以用矢量来完成吗?可以以某种方式存储空值吗?

3 个答案:

答案 0 :(得分:1)

从逻辑上讲,您需要跟踪存在的两个值以及实际存储数据的值。没有最好的方法可以做到这一点,你做出的选择将取决于你正在做什么。

在某些情况下 - 似乎您的实施不是其中之一 - 您可以保留一些特殊值,例如nullptr-1作为哨兵,并使用它来标记空位。你已经提到过,这个选项在这里并不存在,所以我们将这个选项排除在外。

另一个非常合理的选择是在每个插槽中存储并行位向量或一些辅助数据,以标记是否正在使用插槽。如果你使用位向量,那么与你用于元素本身的内容相比,这里所需的额外内存非常小。

上述两种方法的缺点是,如果你有一个真正庞大的阵列 - 比如数百万个元素 - 你将使用大量内存用于未使用的插槽,无论是插槽本身还是任何额外的插槽簿记。另一个选择是使用稀疏数据结构,如std::mapstd::unordered_map,从索引到元素,然后只加载元素到实际使用的稀疏结构。查找单个元素的性能成本有点慢,但内存增益可能很大。

答案 1 :(得分:1)

  

这可以用矢量来完成吗?

没有

当然,除非您使用一些额外的空间来存储该信息(是否存在),或者是否存在不存在的对象的标记值。 std::vector具有根据其存储的元素数量调整自身大小的强大功能;所以,如果它能满足你的要求,就会失去这种能力。

我会使用std::unordered_map,其中每个键都是对象的索引(例如#276),值将是实际对象。如果某个对象不存在,请不要在地图中插入该密钥。

std::map,如果您需要有效地迭代数据。 Choosing between std::map and std::unordered_map

要么认为很难找到将数组的单元格标记为空的标记值。例如,如果你已经在内存中的某个地方(我认为不是你的情况),那么你可以使用一个指针数组,而不是一个存储整个对象的数组。那么很明显,NULL指针将用于空单元格

另一种选择是使用一对数组,如:std::pair<myClass, bool>,其中第二个操作数指示相应的单元格是否为空。

此外,您可以使用std::vector<bool>代替,这非常节省内存(如果您决定采用额外数据结构的方法),如Why does std::vector<bool> has no .data()?中所述。然而,它将缺乏指数表现。

答案 2 :(得分:1)

首先,确保你真的担心有足够的内存来打扰优化。 1000个对象并不多,除非它们很大并且你期望它们稀疏。他们的指数重要吗?也就是说,如果加载2个对象,它们是否可以放入数组的元素0,1,或者它们在数组中的位置是否重要,并且每个对象都有一个必须使用的特定数组索引?如果是这种情况,你最终可能会在数组中出现大洞,并且需要指示哪些元素是否被使用(所以我不建议这样做。)相反,你可能会考虑一个初始化为的指针数组。 null,然后分配使用的元素,并在适当的索引处将相应的指针设置为它们。如果你可以压缩数组,你也可以使用向量。

另一种选择是不将项目放在数组中,而是像树形图一样,它只保存您插入的元素,但仍然可以使用类似于数组索引的键找到它。

(注意:std :: unordered_map比std :: map快,但是哈希表过度分配内存(通常如果使用70%的分配空间,它们被认为是高负载)并且问题的全部目的是减少内存使用量。)