我无法找到这个问题,这是我面临的一个实际问题。
我有一个文件加载实用程序,它返回包含整个文件内容的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>
。
答案 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_cast
到unsigned char
时不会导致陷阱,但我不知道有任何现代硬件或编译器它