如何将std :: vector <unsigned char =“”>转换为vector <char>而不复制?</char> </unsigned>

时间:2013-02-06 00:29:12

标签: c++ vector std

我无法找到这个问题,这是我面临的一个实际问题。

我有一个文件加载实用程序,它返回包含整个文件内容的std::vector<unsigned char>。 但是,处理函数需要char的contiguos数组(并且不能更改 - 它是库函数)。由于使用处理函数的类仍然存储数据的副本,因此我想将其存储为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 个答案:

答案 0 :(得分:7)

在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数组(表示{ {1}}和一个大小),然后你可以在将参数传递给const char*

时进行投射

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

正如您所提到的,一个选项是模板reinterpret_cast<vector<char>&>(cache)并让它返回(或填写)您想要的类型的矢量。另一种方法是复制结果,其简洁版本又是源向量LoadFile()的{​​{1}}。 [basic.fundamental] p1提到“对于字符类型,对象表示的所有位都参与值表示。”,这意味着您不会丢失reinterpret_cast的数据。我没有看到一个确切的保证.data()的位模式在reinterpret_castunsigned char时不会导致陷阱,但我不知道有任何现代硬件或编译器它