将 std::vector 的一部分转换为<char> std::array<char, n>, c++11



以下代码是否违反了严格的混叠或导致了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作为非静态子聚合数据成员的元素。

然而,如果不调用未定义的行为,你仍然不能对结果引用做任何有用的事情,因为有一个不同的规则-§9.3.1 [class.mfct.non-static]/p2:

为对象调用类X的非静态成员函数不属于X类型或X派生类型的行为是未定义的。

还值得注意的是,标准中没有任何规则保证sizeof(std::array<T, N>) == sizeof(T) * N。标准保证的唯一事情是std::array<T, N>是聚合类型,并且可以使用带括号的init-list对其进行初始化,该最多包含N T s。这个实现可以自由地添加额外的东西。

根据do_things的需要,你可能想让你的函数接受随机访问迭代器,或者只是一个指针。或者,如果您希望将函数限制为仅接受std::vectorstd::array s,则可以编写接受const引用的重载,并调用接受const char *的辅助函数来完成实际工作。


新版本没有打破任何规则我能想到的,但它是相当糟糕的设计要求reinterpret_cast几乎每次调用你的函数。如果您不小心将buffer声明为std::vector<std::string>,或者将buffer[0]写成buffer,编译器将愉快地编译您的代码而不发出警告,这可能会导致灾难性的结果。

最新更新