我可以将std :: vector <char>重新解释为std :: vector <unsigned char =“”>而无需复制吗?

时间:2017-01-04 11:12:34

标签: c++ stdvector reinterpret-cast

我有一个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());  

这有多大意义吗?实际发生了什么?

6 个答案:

答案 0 :(得分:3)

  

...是否可以使用std :: move来避免复制或者它已经没有了   被复制

您无法在两个不相关的容器之间移动。 std::vector<char> a std::vector<unsigned char>。因此,在O(1)时间内,&#34;移动〜转换&#34; 彼此的内容是没有合法途径的。

您可以复制:

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) );
    }
}

答案 1 :(得分:1)

我猜你编码了另一个重载函数: -

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>

如果您创建一个可以同时代表Cchar的新课程unsigned char,这是一个更好的主意吗? (例如C::getChar()C::getUnsignedChar(),可能只...存储char但提供转换器作为其非静态函数)

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

然而,在这种情况下,我认为不需要任何优化 对我来说没关系,除非它是性能关键代码。

答案 2 :(得分:1)

如果您的v1类型为std::vector<T1>且需要v2类型std::vector<T2>,则无法复制数据,即使T1和T2为& #34;类似&#34;例如charunsigned char

使用标准库:

std::vector<unsigned char> v2;
std::copy(v1.begin(), v1.end(), std::back_inserter(v2));

围绕它的唯一可行方法是以某种方式仅使用一种类型:如果可能,从一开始就获得std::vector<T2>,或者从现在开始使用std::vector<T1>(可能添加一个处理的重载它)。或者创建可以处理任何[contigous]容器的通用代码(模板)。

  

我认为reinterpret_cast和std :: move应该可以实现   避免复制
  不,它不能   请详细说明 - 为什么不呢?

向量只能从同一类型的另一个向量中窃取资源(移动数据)。它是如何设计界面的。

要做你想做的事,你需要一个release()方法,它将释放底层数据的向量所有权,并将其作为(唯一)指针和移动构造函数/赋值返回,它将从中获取基础数据(独特的)指针。 (即便如此,你仍然需要一个reinterpret_cast,这是......危险区域)

std::vector没有这些。也许应该有。它没有。

答案 3 :(得分:1)

正如其他人已经指出的那样,如果不改变showDataBlock,则无法绕过副本。

我认为你有两个选择:

  1. 扩展showDataBlock以同时处理signed charunsigned char(即将其设为模板)或
  2. 不要将容器作为参数,而是使用迭代器范围。然后,您可以(在value_typechar的情况下)使用特殊迭代器从元素转换为signed charunsigned char

答案 4 :(得分:0)

虽然unsigned charchar是不相关的类型。我认为它们在这种情况下(相同大小的pod)足够相似,以逃避整个模板化类的reinterpret_cast。

static void showDataBlock(bool usefold, bool usecolor,
            std::vector<char> &chunkdata)  
{
  showDataBlock(usefold, usecolor, reinterpret_cast< std::vector<unsigned char>&>(chunkdata));   
}

但是,我倾向于发现这些问题是由于没有设计出最好的架构。看看这个软件应该做的更大的图片来确定你需要使用有符号和无符号字符数据块的原因。

答案 5 :(得分:-3)

我最终做了这样的事情:

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或正常传递 它似乎工作 - 如果它是我不知道的最佳解决方案,但是你们都提出了一些非常好的建议 - 谢谢大家

我同意我无法避免复制,所以我让复制完成正常参数传递

如果您发现此解决方案有误,请在评论中提供更好的解决方案,而不仅仅是downvote