在不复制内存的情况下将 std::vector<std::byte> 分配给 std::vector<char>
Assign std::vector<std::byte> to std::vector<char> WITHOUT copying memory
我有一个函数returns一个std::vector<std::byte>
我知道 std::byte
不是字符类型也不是整数类型,只能通过类型转换将其转换为 char。到目前为止一切顺利。
所以我想(在我知道向量只包含字符数据的情况下)将底层缓冲区的所有权从std::vector<std::byte>
转移到std::vector<char>
使用 std::move
,以避免复制整个底层缓冲区。
当我尝试执行此操作时,出现此错误:
no suitable user-defined conversion from "std::vector<std::byte, std::allocatorstd::byte>" to "std::vector<char,std::allocator>" exists
这完全有可能使用 C++ 吗?
我认为在实际用例中有人会想要这样做
您可以通过强制转换实现这一点,如下所示。这是合法的,因为转换为 char
引用(如果转换为任何其他类型,它将是 UB)但是,至少使用 gcc,您仍然必须使用 -fno-strict-aliasing
编译它以使编译器静音警告。无论如何,这是演员表:
std::vector <char> char_vector = reinterpret_cast <std::vector <char> &&> (byte_vector);
我可能会将数据保留在原始 vector<byte>
中并制作一个小的 class 以保留对原始 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';
}
}
输出:
a
b
c
如果您只需要 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
不允许附加或分离内存分配,除了从完全相同类型的向量移动。这 has been proposed 但人们对用于附加的分配器等提出了(有效的)反对意见。
返回 vector<byte>
的函数会限制您使用 vector<byte>
作为数据容器,除非您想将数据复制出来。
当然,您可以将字节别名 char
就地进行字符操作。
我有一个函数returns一个std::vector<std::byte>
我知道 std::byte
不是字符类型也不是整数类型,只能通过类型转换将其转换为 char。到目前为止一切顺利。
所以我想(在我知道向量只包含字符数据的情况下)将底层缓冲区的所有权从std::vector<std::byte>
转移到std::vector<char>
使用 std::move
,以避免复制整个底层缓冲区。
当我尝试执行此操作时,出现此错误:
no suitable user-defined conversion from "std::vector<std::byte, std::allocatorstd::byte>" to "std::vector<char,std::allocator>" exists
这完全有可能使用 C++ 吗? 我认为在实际用例中有人会想要这样做
您可以通过强制转换实现这一点,如下所示。这是合法的,因为转换为 char
引用(如果转换为任何其他类型,它将是 UB)但是,至少使用 gcc,您仍然必须使用 -fno-strict-aliasing
编译它以使编译器静音警告。无论如何,这是演员表:
std::vector <char> char_vector = reinterpret_cast <std::vector <char> &&> (byte_vector);
我可能会将数据保留在原始 vector<byte>
中并制作一个小的 class 以保留对原始 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';
}
}
输出:
a
b
c
如果您只需要 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
不允许附加或分离内存分配,除了从完全相同类型的向量移动。这 has been proposed 但人们对用于附加的分配器等提出了(有效的)反对意见。
返回 vector<byte>
的函数会限制您使用 vector<byte>
作为数据容器,除非您想将数据复制出来。
当然,您可以将字节别名 char
就地进行字符操作。