【发布时间】:2018-02-14 11:27:47
【问题描述】:
为了有效地获得编译时大小的数组的编译时大小的子范围视图。
我使用这种技术已经有一段时间了,因为我从来没有收到警告或错误,所以我认为它没问题。
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);
直到我找到这些cmetshttps://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-like。
(我认为是。)
【问题讨论】:
-
不确定是不是规则被破坏了,但它是迂腐的UB,
&aa[1]没有对象std::array<int,2>... -
也许如果你改写你的问题,解释你为什么想做你正在做的事情,有人可以建议一种便携的方式来做。我无法确切地说出你为什么要做你正在做的事情,我相信这是有原因的......
-
我认为你打破了这一点:“任何两个具有重叠生命周期的对象(不是位字段)都保证具有不同的地址,除非其中一个是另一个的子对象或提供存储对于另一个,..." 来自:en.cppreference.com/w/cpp/language/object
-
我怀疑如果你真的需要一个类似 std::array 的子数组访问,那么前进的道路将是一些具有 std::array 语义的子范围引用对象。我可以很容易地看到这样一个参考类的优势,可能类似于 std::string_view。
-
我不确定您是否可以依靠 std::array 实现来没有私有管理成员。是的,它们必须毫无例外地构造,因此没有动态分配,并且它们必须封装并表现得像一个 c 样式的数组而不发布任何其他非静态成员,但假设引用“随机数”是不正确的" 内存将正确构造数组。
标签: c++ c++11 strict-aliasing stdarray