2013-02-06 47 views
12

我无法找到这个问题,这是我面临的一个实际问题。如何将std :: vector <unsigned char>转换为矢量<char>而不进行复制?

我有一个文件加载实用程序,返回std::vector<unsigned char>包含整个文件的内容。 但是,处理函数需要连续数组char(并且不能被改变 - 这是一个库函数)。由于使用处理函数的类无论如何都存储数据的副本,因此我想将其存储为vector<char>。这里的代码可能更具说明性。

std::vector<unsigned char> LoadFile (std::string const& path); 

class Processor { 
    std::vector<char> cache; 
    void _dataOperation(std::vector<char> const& data); 

public: 
    void Process() { 
     if (cache.empty()) 
      // here's the problem! 
      cache = LoadFile("file.txt"); 

     _dataOperation(cache); 
    } 
}; 

此代码不编译,因为(显然)没有适当的转换。然而,我们可以肯定,临时向量将占用相同数量的内存(IOW sizeof(char) == sizeof(unsigned char)

幼稚的解决方案是迭代临时内容并投射每个字符。我知道在正常情况下,operator= (T&&)将被调用。

在我的情况下,重新解释转换是安全的,因为我相信我只会读取ASCII字符。无论如何,任何其他角色都会在_dataOperation中被捕。

所以,我的问题是:如何正确和安全地转换临时向量的方式,不涉及复制?

如果这是不可能的,我宁愿复制的安全方式,而不是不安全的非复制。我也可以更换LoadFile返回vector<char>vector<unsigned char>

+1

如果你控制'_dataOperation'的代码,如果你使'vector '长期运行,你可能会更快乐。 – zwol

+0

@Zack不幸的是,我没有。这是一个库函数。我将编辑该问题。 –

+0

没有_safe_的方式 –

回答

6

在C++ 11,[basic.lval] P10说,

如果一个程序试图通过其它一个glvalue比以下类型的行为是一个访问对象的存储值未定义:

  • ...
  • 一个char或unsigned char类型。

(确切位置可能是在C++中的其他版本不同,但意思是相同的。)

这意味着,可以采取一个vector<unsigned char> cache并访问使用范围[reinterpret_cast<char*>(cache.data()), reinterpret_cast<char*>(cache.data()) + cache.size())其内容。 (@Kerrek SB提到了这一点。)

如果存储vector<unsigned char>Processor匹配的LoadFile的返回类型,_dataOperation()实际上采取的char阵列(意思是const char*和大小),那么你就可以施展你的时候“再传递参数_dataOperation()

但是,如果_dataOperation()需要vector<char>专门和你存储vector<unsigned char> cache,那么你不能reinterpret_cast<vector<char>&>(cache)。 (即@AndréPuel是完全错误的,不要听他说)。这违反了别名规则,编译器会在凌晨2点试图激怒你的客户。(如果这个版本的编译器不能管理它,下一个版本将继续尝试。)

正如你所提到的,一种选择是模板LoadFile()并让它返回(或填充)一个向量输入你想要的。另一种方法是复制结果,其中简洁版本再次是源矢量的reinterpret_cast.data()。 [basic.fundamental] p1提到“对于字符类型,对象表示的所有位都参与到值表示中”,这意味着您不会因该reinterpret_cast而丢失数据。如果reinterpret_cast'edchar没有任何现代硬件或编译器,我没有看到一个坚定的保证,即unsigned char的位模式不会引起陷阱。

+0

感谢您的完整答案。 –

相关问题