将 std::vector<std::byte> 分配给 std::vector<char> 而不复制内存

mat*_*att 6 c++ byte vector c++17 stdmove

我有一个函数返回一个 std::vector<std::byte>

我知道这std::byte不是字符类型也不是整数类型,并且只能通过类型转换将其转换为 char。到现在为止还挺好。

所以我想(在我知道向量只包含字符数据的情况下)将底层缓冲区的所有权从 thestd::vector<std::byte>转移到std::vector<char>using std::move,以避免复制整个底层缓冲区。

当我尝试这样做时,我收到此错误:

不存在从“std::vector<std::byte, std::allocatorsstd::byte>”到“std::vector<char,std::allocator>”的合适的用户定义转换

这完全可能使用 C++ 吗?我认为有真正的用例,人们会想要这样做

Ted*_*gmo 7

我可能会将数据保留在原始数据中,vector<byte>并创建一个小类来保留对原始数据的引用vector<byte>,并在您需要时进行必要的转换。

例子:

#include <cstddef>
#include <iostream>
#include <vector>

template<typename T>
struct char_view {
    explicit char_view(std::vector<T>& bytes) : bv(bytes) {}

    char_view(const char_view&) = default;
    char_view(char_view&&) = delete;
    char_view& operator=(const char_view&) = delete;
    char_view& operator=(char_view&&) = delete;

    // capacity
    size_t element_count() const { return bv.size(); }
    size_t size() const { return element_count() * sizeof(T); }

    // direct access
    auto data() const { return reinterpret_cast<const char*>(bv.data()); }
    auto data() { return reinterpret_cast<char*>(bv.data()); }

    // element access
    char operator[](size_t idx) const { return data()[idx]; }
    char& operator[](size_t idx) { return data()[idx]; }

    // iterators - with possibility to iterate over individual T elements
    using iterator = char*;
    using const_iterator = const char*;

    const_iterator cbegin(size_t elem = 0) const { return data() + elem * sizeof(T); }
    const_iterator cend(size_t elem) const { return data() + (elem + 1) * sizeof(T); }
    const_iterator cend() const { return data() + size(); }

    const_iterator begin(size_t elem = 0) const { return cbegin(elem); }
    const_iterator end(size_t elem) const { return cend(elem); }
    const_iterator end() const { return cend(); }
    
    iterator begin(size_t elem = 0) { return data() + elem * sizeof(T); }
    iterator end(size_t elem) { return data() + (elem + 1) * sizeof(T); }
    iterator end() { return data() + size(); }

private:
    std::vector<T>& bv;
};

int main() {
    using std::byte;

    std::vector<byte> byte_vector{byte{'a'}, byte{'b'}, byte{'c'}};

    char_view cv(byte_vector);

    for(char& ch : cv) {
        std::cout << ch << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

a
b
c
Run Code Online (Sandbox Code Playgroud)

如果您只需要const访问权限,一个更简单的选择可能是创建一个string_view

template<typename T>
std::string_view to_string_view(const std::vector<T>& v) {
    return {reinterpret_cast<const char*>(v.data()), v.size() * sizeof(T)};
}
//...
auto strv = to_string_view(byte_vector);
Run Code Online (Sandbox Code Playgroud)

  • @_静态_断言“_用户定义的字节文字_”我完全同意。我试图保持简短,但找不到任何预定义的用户定义字节文字。“_让我们概括这个观点,以帮助传播 UB_”:-) 我认为留在 `char` 应该没问题吧? (3认同)

Pau*_*ers -6

您可以通过强制转换来实现此目的,如下所示。这是合法的,因为强制转换是对char引用的强制转换(如果强制转换为任何其他类型,则为 UB),但至少对于 gcc,您仍然必须使用 来编译它以-fno-strict-aliasing消除编译器警告。无论如何,这是演员阵容:

std::vector <char> char_vector = reinterpret_cast <std::vector <char> &&> (byte_vector);
Run Code Online (Sandbox Code Playgroud)

这是一个现场演示

  • 高射高射高射高射。 (4认同)
  • 既然你带来了大枪,为什么你还需要“std::move”呢?只是 `auto char_vector = reinterpret_cast&lt;std::vector&lt;char&gt; &amp;&amp;&gt;(byte_vector);`。到布法罗大学及其他地方! (3认同)