我可以在不复制的情况下将 std::vector<char> 重新解释为 std::vector<unsigned char> 吗?
Can I reinterpret std::vector<char> as a std::vector<unsigned char> without copying?
我有一个对 std::vector<char>
的引用,我想将其用作接受 std::vector<unsigned char>
的函数的参数。我可以不复制就这样做吗?
我有以下功能并且有效;但是我不确定是否真的发生了复制 - 有人可以帮助我理解这一点吗?是否可以使用 std::move
来避免复制,或者它是否已经没有被复制?
static void showDataBlock(bool usefold, bool usecolor,
std::vector<char> &chunkdata)
{
char* buf = chunkdata.data();
unsigned char* membuf = reinterpret_cast<unsigned char*>(buf);
std::vector<unsigned char> vec(membuf, membuf + chunkdata.size());
showDataBlock(usefold, usecolor, vec);
}
我在想我可以写:
std::vector<unsigned char> vec(std::move(membuf),
std::move(membuf) + chunkdata.size());
这是矫枉过正吗?究竟发生了什么?
我猜你编写了另一个重载函数:-
showDataBlock(usefold, usecolor, std::vector<unsigned char> & vec);
您尝试从 std::vector<T>
转换为另一个 std::vector<T2>
。
无法避免复制。
每个std::vector
都有自己的存储空间,粗略的说就是裸指针
要点是:你不能在多个 std::vector
.
之间共享这样的原始指针
我认为这是设计使然。
我觉得是个好东西,不然就浪费了CPU跟踪
代码...
std::move(membuf)
... 移动原始指针 = 实际上什么都不做。 (与传递 membuf
相同)
要优化,您应该首先验证原因:为什么要从 std::vector<char>
转换为 std::vector<unsigned char>
。
如果您创建一个可以表示为 char
和 unsigned char
的新 class C
是不是更好的主意? (例如 C::getChar()
和 C::getUnsignedChar()
,可能是...仅存储 char
但提供转换器作为其非静态函数)
如果没有帮助,我建议创建一个新的自定义数据结构。
我经常在需要的时候这样做。
但是,在这种情况下,我认为它不需要任何优化。
对我来说没问题,除了它是一个性能关键代码。
如果您有 std::vector<T1>
类型的 v1
并且需要 std::vector<T2>
类型的 v2
则没有办法复制数据,即使 T1 和 T2 "similar" 像 char
和 unsigned char
.
使用标准库:
std::vector<unsigned char> v2;
std::copy(v1.begin(), v1.end(), std::back_inserter(v2));
唯一可能的解决方法是以某种方式只使用一种类型:如果可能的话,从一开始就获得 std::vector<T2>
,或者从现在开始使用 std::vector<T1>
(可能添加一个重载处理它)。或者创建可以处理任何 [contigous] 容器的通用代码(模板)。
I think reinterpret_cast and std::move should make it possible to
avoid copy
no, it can't
please elaborate - why not?
一个向量只能从另一个相同类型的向量窃取资源(移动数据)。它的界面就是这样设计的。
要执行您想要的操作,您需要一个 release() 方法来释放基础数据的矢量所有权,并且 return 它作为(唯一)指针和移动 constructor/assignment将从(唯一)指针获取基础数据。 (即使那样你仍然需要一个 reinterpret_cast
这是......危险区域)
std::vector
有 none 个。也许它应该有。就是没有。
...is it possible to use std::move to avoid copy or is it already not
being copied
您不能在两个不相关的容器之间移动。 a std::vector<char>
是 而不是 a std::vector<unsigned char>
。因此,没有合法的方法可以在 O(1) 时间内 "move ~ convert" 将一个内容传递给另一个内容。
您可以复制:
void showData( std::vector<char>& data){
std::vector<unsigned char> udata(data.begin(), data.end());
for(auto& x : udata)
modify( x );
....
}
或每次访问实时投射...
inline unsigned char& as_uchar(char& ch){
return reinterpret_cast<unsigned char&>(ch);
}
void showDataBlock(std::vector<char>& data){
for(auto& x : data){
modify( as_uchar(x) );
}
}
正如其他人已经指出的那样,如果不更改 showDataBlock
。
就无法绕过副本
我想你有两个选择:
- 扩展
showDataBlock
以在 signed char
和 unsigned char
上工作(即使其成为模板)或
- 不要将容器作为参数,而是将迭代器范围作为参数。然后,您可以(在
value_type
为 char
的情况下)使用从 signed char
元素明智地转换为 unsigned char
的特殊迭代器。
我最终做了这样的事情:
static void showDataBlock(bool usefold,bool usecolor, std::vector<char> chunkdata)
{
std::vector<unsigned char>&cache = reinterpret_cast<std::vector<unsigned char>&>(chunkdata);
showDataBlock(usefold, usecolor, cache);
}
static bool showDataBlock(bool usefold,bool usecolor, std::vector<unsigned char> &chunkdata)
{
// showing the data
}
这个解决方案允许我将矢量作为 ref 或正常传递
它似乎在工作 - 如果它是我不知道的最佳解决方案,但是你们都提出了一些非常好的建议 - 谢谢大家
我同意我无法避免复制,所以我让复制通过正常的参数传递完成
如果您发现此解决方案有误,请在评论中提供更好的解决方案,而不仅仅是投反对票
而 unsigned char
和 char
是不相关的类型。我认为它们在这种情况下足够相似(相同大小 pods),可以摆脱整个模板 class.
的 reinterpret_cast
static void showDataBlock(bool usefold, bool usecolor,
std::vector<char> &chunkdata)
{
showDataBlock(usefold, usecolor, reinterpret_cast< std::vector<unsigned char>&>(chunkdata));
}
然而,我倾向于发现这些问题是由于没有设计出最好的架构。查看该软件应该做什么的更大图景,以确定您需要使用带符号和无符号字符数据块的原因。
我有一个对 std::vector<char>
的引用,我想将其用作接受 std::vector<unsigned char>
的函数的参数。我可以不复制就这样做吗?
我有以下功能并且有效;但是我不确定是否真的发生了复制 - 有人可以帮助我理解这一点吗?是否可以使用 std::move
来避免复制,或者它是否已经没有被复制?
static void showDataBlock(bool usefold, bool usecolor,
std::vector<char> &chunkdata)
{
char* buf = chunkdata.data();
unsigned char* membuf = reinterpret_cast<unsigned char*>(buf);
std::vector<unsigned char> vec(membuf, membuf + chunkdata.size());
showDataBlock(usefold, usecolor, vec);
}
我在想我可以写:
std::vector<unsigned char> vec(std::move(membuf),
std::move(membuf) + chunkdata.size());
这是矫枉过正吗?究竟发生了什么?
我猜你编写了另一个重载函数:-
showDataBlock(usefold, usecolor, std::vector<unsigned char> & vec);
您尝试从 std::vector<T>
转换为另一个 std::vector<T2>
。
无法避免复制。
每个std::vector
都有自己的存储空间,粗略的说就是裸指针
要点是:你不能在多个 std::vector
.
之间共享这样的原始指针
我认为这是设计使然。
我觉得是个好东西,不然就浪费了CPU跟踪
代码...
std::move(membuf)
... 移动原始指针 = 实际上什么都不做。 (与传递 membuf
相同)
要优化,您应该首先验证原因:为什么要从 std::vector<char>
转换为 std::vector<unsigned char>
。
如果您创建一个可以表示为 char
和 unsigned char
的新 class C
是不是更好的主意? (例如 C::getChar()
和 C::getUnsignedChar()
,可能是...仅存储 char
但提供转换器作为其非静态函数)
如果没有帮助,我建议创建一个新的自定义数据结构。
我经常在需要的时候这样做。
但是,在这种情况下,我认为它不需要任何优化。
对我来说没问题,除了它是一个性能关键代码。
如果您有 std::vector<T1>
类型的 v1
并且需要 std::vector<T2>
类型的 v2
则没有办法复制数据,即使 T1 和 T2 "similar" 像 char
和 unsigned char
.
使用标准库:
std::vector<unsigned char> v2;
std::copy(v1.begin(), v1.end(), std::back_inserter(v2));
唯一可能的解决方法是以某种方式只使用一种类型:如果可能的话,从一开始就获得 std::vector<T2>
,或者从现在开始使用 std::vector<T1>
(可能添加一个重载处理它)。或者创建可以处理任何 [contigous] 容器的通用代码(模板)。
I think reinterpret_cast and std::move should make it possible to avoid copy
no, it can't
please elaborate - why not?
一个向量只能从另一个相同类型的向量窃取资源(移动数据)。它的界面就是这样设计的。
要执行您想要的操作,您需要一个 release() 方法来释放基础数据的矢量所有权,并且 return 它作为(唯一)指针和移动 constructor/assignment将从(唯一)指针获取基础数据。 (即使那样你仍然需要一个 reinterpret_cast
这是......危险区域)
std::vector
有 none 个。也许它应该有。就是没有。
...is it possible to use std::move to avoid copy or is it already not being copied
您不能在两个不相关的容器之间移动。 a std::vector<char>
是 而不是 a std::vector<unsigned char>
。因此,没有合法的方法可以在 O(1) 时间内 "move ~ convert" 将一个内容传递给另一个内容。
您可以复制:
void showData( std::vector<char>& data){
std::vector<unsigned char> udata(data.begin(), data.end());
for(auto& x : udata)
modify( x );
....
}
或每次访问实时投射...
inline unsigned char& as_uchar(char& ch){
return reinterpret_cast<unsigned char&>(ch);
}
void showDataBlock(std::vector<char>& data){
for(auto& x : data){
modify( as_uchar(x) );
}
}
正如其他人已经指出的那样,如果不更改 showDataBlock
。
我想你有两个选择:
- 扩展
showDataBlock
以在signed char
和unsigned char
上工作(即使其成为模板)或 - 不要将容器作为参数,而是将迭代器范围作为参数。然后,您可以(在
value_type
为char
的情况下)使用从signed char
元素明智地转换为unsigned char
的特殊迭代器。
我最终做了这样的事情:
static void showDataBlock(bool usefold,bool usecolor, std::vector<char> chunkdata)
{
std::vector<unsigned char>&cache = reinterpret_cast<std::vector<unsigned char>&>(chunkdata);
showDataBlock(usefold, usecolor, cache);
}
static bool showDataBlock(bool usefold,bool usecolor, std::vector<unsigned char> &chunkdata)
{
// showing the data
}
这个解决方案允许我将矢量作为 ref 或正常传递 它似乎在工作 - 如果它是我不知道的最佳解决方案,但是你们都提出了一些非常好的建议 - 谢谢大家
我同意我无法避免复制,所以我让复制通过正常的参数传递完成
如果您发现此解决方案有误,请在评论中提供更好的解决方案,而不仅仅是投反对票
而 unsigned char
和 char
是不相关的类型。我认为它们在这种情况下足够相似(相同大小 pods),可以摆脱整个模板 class.
static void showDataBlock(bool usefold, bool usecolor,
std::vector<char> &chunkdata)
{
showDataBlock(usefold, usecolor, reinterpret_cast< std::vector<unsigned char>&>(chunkdata));
}
然而,我倾向于发现这些问题是由于没有设计出最好的架构。查看该软件应该做什么的更大图景,以确定您需要使用带符号和无符号字符数据块的原因。