通过引用访问是否违反了严格的别名规则?

时间:2015-11-21 22:57:26

标签: c++ strict-aliasing

我知道int* ptr = (int*)buffer(其中bufferchar*)会中断 严格别名规则。

这种语法int& ref = (int&)(*buffer)是否也违反了规则?

由于违反了严格的别名规则,我had了一些SEGFAULT,这种语法已经消除了这一点。虽然可能仍然不正确,是吗?

3 个答案:

答案 0 :(得分:3)

这不行(假设您将使用所述引用来访问该值)。 §3.10[basic.lval]¶10C ++ 14标准(引用N4140)说(强调我的):

  

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

     
      
  • 对象的动态类型,
  •   
  • 对象的动态类型的cv限定版本,
  •   
  • 与对象的动态类型相似的类型(如4.4中所定义)
  •   
  • 与对象的动态类型对应的有符号或无符号类型的类型
  •   
  • 对应于动态类型的cv限定版本的有符号或无符号类型   对象,
  •   
  • 聚合或联合类型,包括其元素或非静态数据成员中的上述类型之一(递归地,包括子聚合的元素或非静态数据成员)   或包含联盟),
  •   
  • 一种类型,它是对象动态类型的(可能是cv限定的)基类类型,
  •   
  • charunsigned char类型。
  •   

您是否尝试通过指针或引用进行访问无关紧要。对于char类型的存储对象,没有一个项目符号适用于允许它作为int访问它。

最后一个要点仅表示您可以将任何其他类型别名为char,但反之亦然。这是有道理的,因为char是具有最弱对齐要求的最小可寻址单元。

如果需要,使用指针与使用引用相同,除非您需要显式取消引用才能访问该值。

答案 1 :(得分:2)

严格的别名规则意味着你不应该取消引用指向同一内存位置的不同类型的指针。

由于在您发布的代码中您永远不会取消引用,因此无法在不查看所有代码的情况下判断是否违反规则。

此外,别名为char *类型是一个例外,并且不违反规则。这意味着您可以通过将其指针转换为char *并取消引用来访问包含任何类型的内存位置。

总结:

  • 如果buffer指向包含int的内存位置,并且已从int*转换为char*,则此选项有效。但是,您应该使用reinterpret_cast作为此
  • 如果缓冲区指向包含字符的内存位置,则取消引用int* ptr会违反规则。
  • 参考版本可能会遇到同样的问题。但编译器没有义务阻止或警告您这样做
  • 不要使用C样式转换,请改用reinterpret_cast,并阅读有关哪些用途已定义行为的标准。

答案 2 :(得分:2)

是的,确实如此。

C和C ++特殊情况都不能通过指针与其他访问进行访问,无论您使用指针,引用还是任何其他左值,严格的别名规则都适用。

如果遇到麻烦,最简单的解决方案是使用memcpy将内存位置复制到局部变量中 - 任何自尊的编译器都会完全优化这个memcpy,只将其视为别名提示(memcpy也是首选)在工会上,因为工会方法不那么便携。)