如何将一种类型的多个值合并为另一种类型中的单个值
How to merge several values of one type into a single value of another type
E.g给定长度为100的vector<uint8>
,如何创建50个元素的新vector<uint16>
。最好不要复制?
(编辑:我的评论信息(
举例说明:
我有一个uint16灰度图像文件,我的第三方lib返回uint8的向量。每2个字节=1个像素。对我来说,使用uint16的向量是实用的。我认为这个vector<uint8>
和相应的vector<uint16>
之间的唯一区别是,字节是以"级联"的方式读取的(即,2个字节的块=1个值(。
我可以循环并将每2个元素组合成一个新的向量元素,但这似乎效率很低,因为内存布局是相同的。我希望我可以结合一些强制转换和移动构造函数来创建一个vector<uint16>
——而不需要再次复制原始的vector<uint8>
字节。
编辑2:为了消除任何可能的误解,我画了一幅画,请原谅我糟糕的ascii艺术:(
内存中uint8值的容器:
[_]|[_]|[_]
|^^|
访问元素=访问1字节
内存中uint16值的容器也是一个字节序列;
[_]|[_]|[_]
|^^^^|
访问元素=访问2个字节(比如我的系统将其读取为big-endian(
我已经有了向量v1中的字节序列。我只想要一个不同类型的v2,这样我就可以以不同的方式访问它们。如果结果是uint16值被读取为little-endian,我仍然可以使用它。
编辑3:到目前为止,布莱克的答案似乎是我所理解的最好的(如果没有任何变化,我稍后会接受(,但没有简单或STL的解决方案似乎仍然很奇怪。尽管如此,还是要感谢大家对我解释自己的及时投入和耐心。
由于您不控制源(根据注释(,您无法知道输入向量有一个2字节对齐的缓冲区。仅出于这个原因,您就必须复制输入向量。
你怎么做并不重要;内存访问速度可能会主导运行时间。但是,请在目标向量上调用reserve(50)
-具有多个分配将减慢程序速度。
您可以编写一个包装器,以便在需要时为您进行转换。例如(无模板(
static inline uint16 getElement(const vector<uint8> &p, size_t index) {
const int idx = index * 2;
return p[idx] | p[idx + 1] << 8;
}
vector<std::uint8_t>
将保持一个std::uint8_t*
,而vector<std::uint16_t>
将保持std::uint16_t*
。你想做的基本上是分享这两个指针,并给出不同的解释,比如
auto ptr = reinterpret_cast<std::uint16_t*>( vectorOfUint8.data() )
只要您不通过该指针读/写,这是可以的,因为由于严格的别名规则,这样的操作将导致未定义的行为。您需要进行复制,使用SIMD可以对其进行优化,使其非常高效。如果你的编译器不能自动完成,你可以使用内部函数或展开它:
- 从v1到v2读取两个元素,使它们手动获得96(v2中为48(
- 在v2上循环并一次读取4个(i+=48/4=12(或8个(i+-=48/8=6(元素
您也可以禁用严格的别名规则,尽管这是编译器特定的,因此不是标准的和可移植的。
您必须进行类型转换,在这种情况下,我认为您不会在不复制的情况下进行。
矢量是一个连续的内存块,uint8
将导致所有数字占据8位,并且在内存中相邻。现在,当您将其转换为uint16
时,每个数字都需要额外的8位,并且您无法神奇地在连续块之间插入内存。因此,复制将发生。
如果没有不复制的限制,这个问题并不难,我相信你可以解决。
编辑:作为对注释的回应,即使向量有100个元素的空间,但其中的元素少于50个,类型转换仍然需要复制。前两个元素将占用16位,而稍后第一个元素将占据这16位。因此,您必须至少复制第二个元素。在类似的逻辑中,您将不得不复制其他元素。
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- C++ 超载 += 用于两个袋子的合并,返回类型为空隙
- 使用template-template参数从可变模板合并类型
- 如何将一种类型的多个值合并为另一种类型中的单个值
- 静态类型语言中的合并运算符
- c++合并:ld: fatal:文件主.O:未知文件类型