这是未定义的行为吗?
std::array<int, 5> x = {3, 5, 1, 2, 3};
std::array<int, 3>& y = *reinterpret_cast<std::array<int, 3>*>(&x[1]);
for(int i = 0; i != 3; i++) {
std::cout << y[i] << "\n";
}
也许是的,但我觉得应该有一种安全方式来切片std::array
。
编辑:按照拉德克的建议:
template<unsigned N, unsigned start, unsigned end, typename T>
std::array<T, end - start>& array_slice(std::array<T, N>& x)
{
static_assert(start <= end, "start <= end");
static_assert(end <= N-1, "end <= N");
return *reinterpret_cast<std::array<T, end - start>*>(&x[start]);
}
编辑:好的,我觉得我对std::array
感到不满意,并会转向其他任何想法?
答案 0 :(得分:6)
是的,这是未定义的行为。你正在采用一种类型,reinterpret_cast
将它转换为另一种类型。事实上,使用reinterpret_cast
应该是“这里有龙!”的大红旗。
对于切片阵列,这不会发生。 std::array
包含值;一部分将包含引用到该数组的一部分。因此,它不会是std::array
。您可以复制数组切片,但不能使用std::array
。您需要使用std::vector
,因为它允许调用构造函数,以及从一系列值构造。请记住:std::array
只是围绕C风格数组的更好的包装器。
委员会正在调查模板array_ref<T>
类,这正是它所说的:对T
类型数组的某些段的引用。这可以是常规的C风格数组,std::vector
,std::array
,或者仅使用new T[]
分配的内存。有some library implementations of the class already,但没有标准化。
按照拉德克的建议:
隐藏函数中的未定义行为不会使其定义行为。您可以尝试假装它没有未定义,但它仍然是。你使用reinterpret_cast
的那一刻,你愿意放弃生活在C ++中的土地。
答案 1 :(得分:-1)
新的展示位置怎么样?
#include <array>
#include <iostream>
#include <iterator>
template<typename T, std::size_t N>
struct array_slice : public std::array<T,N> {
~array_slice() = delete;
};
int main() {
std::array<double,4> x_mu{0.,3.14,-1.,1.};
std:: cout << &x_mu << std::endl;
{
auto slicer = [] (std::array<double,4>& ref) {
array_slice<double,3>* p = new (&ref) array_slice<double,3>;
return p;
};
std::array<double,3>& x_ = *slicer(x_mu);
std::copy(x_.begin(),x_.end(),
std::ostream_iterator<float>(std::cout," "));
std:: cout << std::endl;
std:: cout << &x_ << std::endl;
}
std::copy(x_mu.begin(),x_mu.end(),
std::ostream_iterator<float>(std::cout," "));
}