简体   繁体   English

分配 std::vector<std::byte> 到 std::vector<char> 不复制 memory</char></std::byte>

[英]Assign std::vector<std::byte> to std::vector<char> WITHOUT copying memory

I have a function that returns a std::vector<std::byte>我有一个返回std::vector<std::byte>的 function

I am aware that std::byte is not a character type nor an integral type, and that converting it to char is only possible through a typecast.我知道std::byte不是字符类型也不是整数类型,并且只能通过类型转换将其转换为 char 。 So far so good.到目前为止,一切都很好。

So I would like (in cases where I know that the vector only contains character data) to transfer ownership of the underlying buffer from the std::vector<std::byte> to a std::vector<char> using std::move , so as to avoid copying the entire underlying buffer.所以我想(在我知道向量只包含字符数据的情况下)使用 std:: 将底层缓冲区的所有权从std::vector<std::byte>转移到 std std::move std::vector<char> std::move ,以避免复制整个底层缓冲区。

When I try doing this, I get this error:当我尝试这样做时,我收到此错误:

no suitable user-defined conversion from "std::vector<std::byte, std::allocatorstd::byte>" to "std::vector<char,std::allocator>" exists不存在从“std::vector<std::byte, std::allocatorsstd::byte>”到“std::vector<char,std::allocator>”的合适的用户定义转换

Is this at all possible using C++?使用 C++ 是否有可能? I think there are real use cases where one would want to do this我认为有真正的用例想要这样做

I would probably leave the data in the original vector<byte> and make a small class that keeps a reference to the original vector<byte> and does the necessary casting when you need it.我可能会将数据留在原始vector<byte>中,并制作一个小的 class 来保留对原始vector<byte>的引用,并在需要时进行必要的转换。

Example:例子:

#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';
    }
}

Output: Output:

a
b
c

A simpler option if you only need const access could be to create a string_view :如果您只需要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);

std::vector does not allow attaching or detaching to memory allocations, other than moves from a vector of exactly the same type. std::vector不允许附加或分离到 memory 分配,除了从完全相同类型的向量移动。 This has been proposed but people raised (valid) objections about the allocator for attaching and so on.已被提出,但人们对附加分配器等提出了(有效的)反对意见。

The function returning vector<byte> constrains you to work with a vector<byte> as your data container unless you want to copy the data out. function 返回vector<byte>会限制您使用vector<byte>作为数据容器,除非您想将数据复制出来。

Of course, you can alias the bytes as char in-place for doing character operations.当然,您可以将字节别名为char就地进行字符操作。

You can achieve this with a cast, as shown below.您可以通过强制转换来实现这一点,如下所示。 This is legal because the cast is to a char reference (if casting to any other type it would be UB) but, with gcc at least, you still have to compile it with -fno-strict-aliasing to silence the compiler warning.这是合法的,因为转换是针对char引用(如果转换为任何其他类型,它将是 UB),但是至少使用 gcc,您仍然必须使用-fno-strict-aliasing编译它以使编译器警告静音。 Anyway, here's the cast:无论如何,这是演员表:

std::vector <char> char_vector = reinterpret_cast <std::vector <char> &&> (byte_vector);

And here's a live demo这是一个现场演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM