变量中内存的简单重叠是否违反了别名规则?

时间:2018-02-14 11:27:48

标签: c++ c++11 strict-aliasing stdarray

为了有效地编译时间大小的编译时大小的数组的子范围视图。

我一直在使用这种技术,因为我从来没有收到警告或错误,我认为没问题。

std::array<int,3> aa = {{1,2,3}};
std::array<int,2>& ee = reinterpret_cast<std::array<int,2>&>(aa[1]); // subrange {{2,3}}
assert(ee[0] == 2);

直到我找到这些评论https://stackoverflow.com/a/36046533/225186

我可以让gcc用这个

发出警告
int aaa = 5;
double& eee = reinterpret_cast<double&>(aaa);

或者

std::array<int,3> aaaa = 5;
std::array<double,2>& eeee = reinterpret_cast<std::array<double,2>&>(aaaa);

...但不是第一个代码块。

如果两个引用不完全在同一个地址中,似乎没有强制执行别名规则?

每个人似乎都同意这至少是UB。 这样可以吗?或者甚至是最糟糕的?

int aa[3] = {1,2,3};
int* ee = new(&aa[1]) int[2];

如果我可以说int ee[2] = new(&aa[1]) int[2];,那将是完美的,因为ee的类型将带有新的大小,我可以递归地使用子视图。

我可以使用std::basic_string_view<int>吗? 在cppreference,唯一的限制是int必须是char - 就像。 (我认为是这样。)

1 个答案:

答案 0 :(得分:1)

std::array<int,3> aa = {{1,2,3}};
std::array<int,2>& ee = reinterpret_cast<std::array<int,2>&>(aa[1]);

绝对会破坏严格的别名规则,对ee的访问权限为未定义的行为

请参阅cppreference/reinterpret_cast/type aliasing

enter image description here

  

...但不是第一段代码。

如果您的编译器没有产生警告,那么它并不意味着一切正常 - 标准不强制要求警告。编译器尽可能地提供帮助,但它们不会检测到所有标准违规行为。