C++ 强制转换std::vector的一部分<;char>;到std::数组<;字符,n>;,c++;11

C++ 强制转换std::vector的一部分<;char>;到std::数组<;字符,n>;,c++;11,c++,c++11,C++,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> &

根据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]));
}

根据我对别名的理解,这不应导致未定义的行为,并捕获传递固定大小数组的语义。我的理解正确吗?

严格的别名规则涉及§3.10[basic.lval]/p10,其中规定

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

  • 对象的动态类型
  • 对象动态类型的cv限定版本
  • 与对象的动态类型类似的类型(如4.4中所定义)
  • 与对象的动态类型相对应的有符号或无符号类型
  • 一种类型,它是与对象的动态类型的cv限定版本相对应的有符号或无符号类型
  • 在其元素或非静态数据成员中包含上述类型之一的聚合或联合类型(包括, 递归地,子集合或子集合的元素或非静态数据成员 (包含的联合)
  • [……]
因此,通过类型为
std::array
的glvalue访问类型为
char
的对象不会违反此规则,因为
std::array
是一种聚合类型,它包括
char
作为非静态子聚合数据成员的元素


但是,由于不同的规则-§9.3.1[class.mfct.non static]/p2:

如果为对象调用类
X
的非静态成员函数 这不是
X
类型,也不是从行为
X
派生的类型 没有定义

还值得注意的是,标准中没有任何规则保证
sizeof(std::array)==sizeof(T)*N
。标准唯一能保证的是,
std::array
是一种聚合类型,可以使用包含多达
N
T
s的带括号的init列表对其进行初始化。实现可以自由添加额外的内容

根据
所需的操作,您可能希望让函数使用随机访问迭代器,或者只使用一个指针。或者,如果您希望将函数限制为只接受
std::vector
std::array
s,则可以编写重载,将常量引用带到这些函数,并调用执行实际工作的助手函数



新版本并没有打破我能想到的任何规则,但它的设计相当糟糕,要求几乎每次调用函数时都要使用
reinterpret\u cast
。如果您意外地将
buffer
声明为
std::vector
,或编写了
buffer
而不是
buffer[0]
,编译器将在没有警告的情况下愉快地编译您的代码,有潜在的灾难性后果。

相关:有什么理由不编写基于迭代器的通用解决方案吗?当然,这会打破严格的别名。此外,
std::array
甚至不能保证除了元素之外没有其他数据成员…@HerpDerpington仅供参考,随机访问迭代器不能保证连续存储。提供这样的迭代器,例如,没有这样的连续存储保证。但是,如果您可以使用随机访问迭代器,那么基于迭代器的解决方案上的SFINAE启用策略就足够了。值得思考。@HerpDerpington它必须是一个聚合,并且您必须能够使用
数组a={initializer list}初始化它如果初始值设定项列表最多为
N
逗号分隔
T
s。但是没有规则规定实现不能放入额外的内容。
std::vector
保证连续内存(如果您需要的话)。§9.3.1[class.mfct.non static]/p2冲突发生,因为索引std::数组调用运算符[],对吗?@HerpDerpington正确。
void do_things(const char (&block)[64]) {
   // ...
}

int main() {
    std::vector<char> buffer(64);
    do_things(reinterpret_cast<char (&)[64]>(buffer[0]));
}