C++ 我可以将std::数组强制转换为切片吗?或者还有什么我可以用的吗?
这是未定义的行为吗C++ 我可以将std::数组强制转换为切片吗?或者还有什么我可以用的吗?,c++,arrays,stl,c++11,C++,Arrays,Stl,C++11,这是未定义的行为吗 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
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
s不满意,并将转向其他方面,有什么想法吗?是的,这是未定义的行为。您正在使用一种类型并将其重新解释为另一种类型。事实上,使用reinterpret_cast
应该是“这里有龙!”
至于切片阵列,这是不会发生的。std::array
包含值;其中的一个片段将包含对该数组一部分的引用。因此,它将不是一个std::array
。您可以复制数组的切片,但不能使用std::array
。您需要使用std::vector
,因为它允许调用构造函数以及从一系列值进行构造。请记住:std::array
只是C样式数组的更好包装
委员会正在研究一个模板array\u ref
类,这正是它所说的:对T
类型数组的某个部分的引用。这可能是一个常规的C样式数组、一个std::vector
、一个std::array
,或者只是一些分配了newt[]
的内存。有,但还没有标准化
根据Radek的建议:
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]);
}
在函数中隐藏未定义的行为不会使其成为已定义的行为。你可以假装它不是未定义的,但它仍然是。当你使用这个
重新解释
的时候,你就会心甘情愿地放弃在C++世界的生活。一个新的安置怎么样
#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," "));
}
#包括
#包括
#包括
模板
结构数组\u切片:public std::array{
~array_slice()=删除;
};
int main(){
std::数组x_mu{0,3.14,-1,1};
std::cout但我真的觉得应该有一种安全的方法来分割std::array编写一个模板函数array_cast
@Giovanni:只有当你试图将它用于它不打算用于的东西时,它才会被破坏。这就像说std::list
被破坏是因为它的元素没有连续存储,或者说代码不正确,因为它不提供O(1)查找。你希望锤子充当螺丝刀。”乔凡尼:“C数组完全有效的东西对于C++是无效的。”不,不是。它只是“有效的”。当这些数组退化为指针时,使用C数组。在这一点上,它们不再是数组;它们是指针。您不能将int[5]
转换为int[3]
;您可以将其转换为int*
,但这是另一种构造。std::array
所做的是将衰减为指针,以便数组始终保持为数组(除非您显式地衰减它们,此时您愿意放弃安全性)。这就是array\u ref
的全部内容。@Giovanni:这个讨论是关于C++11的,而不是C99。在C++11中,从int[5]
转换到int[3]
是未定义的行为。@GiovanniFunchal你是在引用6.5.6加法运算符吗?如果是,这不支持从int[5]
转换到int[3]
在C99中有很好的定义。虽然将int[5]
转换为int[3]
是未定义的行为,但很难提出一个合理的标准投诉实现,其中int[3]
和int[5]
不兼容布局,更不用说实际存在于野外的布局了。有人能提供吗?reinterpret\u cast
并不意味着“未定义的行为”如果要重新解释的对象与布局兼容。这是各种未定义的行为。通过重用旧数组元素的内存,可以结束其生命周期。可以在相同位置创建新元素,但允许现有引用/指针引用相同位置的新对象的规则仅适用于完整对象,这些是聚合的子对象。根据元素类型的不同,它可能具有清除现有值的非平凡默认初始化,或者您可能最终得到未初始化的对象(不能假定这些对象采用以前存在于其内存位置中的值)。