我可以在不复制的情况下将 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>

如果您创建一个可以表示为 charunsigned char 的新 class C 是不是更好的主意? (例如 C::getChar()C::getUnsignedChar(),可能是...仅存储 char 但提供转换器作为其非静态函数)

如果没有帮助,我建议创建一个新的自定义数据结构。
我经常在需要的时候这样做。

但是,在这种情况下,我认为它不需要任何优化。
对我来说没问题,除了它是一个性能关键代码。

如果您有 std::vector<T1> 类型的 v1 并且需要 std::vector<T2> 类型的 v2 则没有办法复制数据,即使 T1 和 T2 "similar" 像 charunsigned 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

就无法绕过副本

我想你有两个选择:

  1. 扩展 showDataBlock 以在 signed charunsigned char 上工作(即使其成为模板)或
  2. 不要将容器作为参数,而是将迭代器范围作为参数。然后,您可以(在 value_typechar 的情况下)使用从 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 charchar 是不相关的类型。我认为它们在这种情况下足够相似(相同大小 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));   
}

然而,我倾向于发现这些问题是由于没有设计出最好的架构。查看该软件应该做什么的更大图景,以确定您需要使用带符号和无符号字符数据块的原因。