以下代码是否违反了严格的混叠或导致了c++ 11标准中未定义的行为?是否有更好的方法来实现相同的功能?
void do_things(const std::array<char, 64> &block) {
// ...
}
int main() {
std::vector<char> buffer(64);
do_things(reinterpret_cast<const std::array<char, 64> &>(buffer[0]));
}
tldr:使用const char *
不那么痛苦
编辑:由于sizeof(std::array<char, n>)
不能保证等于n
,我提出以下建议:
void do_things(const char (&block)[64]) {
// ...
}
int main() {
std::vector<char> buffer(64);
do_things(reinterpret_cast<char (&)[64]>(buffer[0]));
}
根据我对混叠的理解,这不应该导致未定义的行为,并捕获传递固定大小的数组的语义。我的理解对吗?
严格混叠规则参考§3.10[基本]。Lval]/p10,它提供
如果程序试图通过该行为不是下列类型之一的全局值定义:
- 对象的动态类型,
- 对象动态类型的cv限定版本,
- 与对象的动态类型相似的类型(定义见4.4),
- 与对象的动态类型对应的有符号或无符号类型的类型,
- 有符号或无符号类型,对应于对象动态类型的cv限定版本,
- 聚合或联合类型,在其元素或非静态数据成员(包括:类的元素或非静态数据成员包含联盟)
- […]
因此,通过std::array<char, N>
类型的glvalue访问char
类型的对象不会违反此规则,因为std::array<char, N>
是一个聚合类型,它将char
作为非静态子聚合数据成员的元素。
为对象调用类
X
的非静态成员函数不属于X
类型或X
派生类型的行为是未定义的。
还值得注意的是,标准中没有任何规则保证sizeof(std::array<T, N>) == sizeof(T) * N
。标准保证的唯一事情是std::array<T, N>
是聚合类型,并且可以使用带括号的init-list对其进行初始化,该最多包含N
T
s。这个实现可以自由地添加额外的东西。
根据do_things
的需要,你可能想让你的函数接受随机访问迭代器,或者只是一个指针。或者,如果您希望将函数限制为仅接受std::vector
和std::array
s,则可以编写接受const引用的重载,并调用接受const char *
的辅助函数来完成实际工作。
新版本没有打破任何规则我能想到的,但它是相当糟糕的设计要求reinterpret_cast
几乎每次调用你的函数。如果您不小心将buffer
声明为std::vector<std::string>
,或者将buffer[0]
写成buffer
,编译器将愉快地编译您的代码而不发出警告,这可能会导致灾难性的结果。