gpt4 book ai didi

c++ - 如何以 "union-like"的方式更改 C++ vector 的数据类型

转载 作者:行者123 更新时间:2023-12-01 22:17:40 49 4
gpt4 key购买 nike

我想知道在 C++ 中是否可以更改已填充值的 std::vector 的类型,就像 union 的工作方式一样,即:

  • 不更改二进制内容的任何一位
  • 不计算任何类型转换(无数学运算)
  • 只是使用新类型(例如 uint16 或 float32)重新解释二进制数据的内容,没有任何内存复制或重新分配(因为我想使用几 GB 大小的 vector )

例如,我有一个填充了 20 个值的 vector :0x00、0x01、0x02、0x03 ...我想将其重新解释为 10 个值的 vector ,具有相同的整体二进制内容:0x0001、0x0203(取决于小端/大端约定)

我能做的最接近的事情是:

vector<uint8_t> test8(20);
uint16_t* pv16 = (uint16_t*) (&test8[0]);
vector<uint16_t> test16(pv16, pv16+10);

结果正是我想要的,只是它复制了整个数据,而我想使用现有数据。

如果您对此主题有任何帮助,我将不胜感激。

非常感谢您的回答。

最佳答案

您可能不需要一个完整的 vector ,只需要一些行为类似于容器的东西。您可以创建自己的 punned_view,它仅引用现有 vector 中的内存。

另请阅读 C++ 中的类型双关和未定义行为,因为这是一个非常微妙的主题。请参阅https://blog.regehr.org/archives/959

#include <type_traits>
#include <cstring>
#include <cstdint>
#include <vector>

template <typename To>
class punned_view
{
static_assert(std::is_trivial<To>::value);
const char* begin_;
const char* end_;
public:
template <typename From>
punned_view(From* begin, From* end)
: begin_{reinterpret_cast<const char*>(begin)}
, end_{reinterpret_cast<const char*>(end)}
{
static_assert(sizeof(To) >= sizeof(From)); // exercise to make it work with smaller types too
static_assert(std::is_trivial<From>::value);
// add checks that size is a multiple of To here
}

std::size_t size() const noexcept
{
return (end_ - begin_) / sizeof(To);
}

class const_iterator
{
const char* current_;
public:
const_iterator(const char* current)
: current_{current}
{ }

const_iterator& operator++() noexcept
{
current_ += sizeof(To);
return *this;
}
To operator*() const noexcept
{
To result;
// only legal way to type pun in C++
std::memcpy(&result, current_, sizeof(result));
return result;
}
bool operator != (const_iterator other) const noexcept
{
return current_ != other.current_;
}
};

const_iterator begin() const noexcept { return {begin_}; }
const_iterator end() const noexcept { return {end_}; }
};

uint16_t sum_example(const std::vector<uint8_t>& vec)
{
punned_view<uint16_t> view{vec.data(), vec.data() + vec.size()};

uint16_t sum = 0;
for (uint16_t v : view)
sum += v;

return sum;
}

关于c++ - 如何以 "union-like"的方式更改 C++ vector 的数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59743297/

49 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com