繁体   English   中英

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

[英]Casting a section of a std::vector<char> to 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[basic.lval] / p10,它提供了这一点

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

  • 对象的动态类型,
  • 一个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>是一种聚合类型,它可以使用包含最多N T s的braced-init-list进行初始化。 实现可以免费添加额外的东西。

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


新版本没有破坏我能想到的任何规则,但是每次调用函数时都要求reinterpret_cast几乎被使用,这是相当糟糕的设计。 如果您不小心将buffer声明为std::vector<std::string> ,或者写入buffer而不是buffer[0] ,编译器将很乐意编译您的代码而不会发出警告,结果可能会带来灾难性后果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM