Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以将std::数组强制转换为切片吗?或者还有什么我可以用的吗?_C++_Arrays_Stl_C++11 - Fatal编程技术网

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
并不意味着“未定义的行为”如果要重新解释的对象与布局兼容。这是各种未定义的行为。通过重用旧数组元素的内存,可以结束其生命周期。可以在相同位置创建新元素,但允许现有引用/指针引用相同位置的新对象的规则仅适用于完整对象,这些是聚合的子对象。根据元素类型的不同,它可能具有清除现有值的非平凡默认初始化,或者您可能最终得到未初始化的对象(不能假定这些对象采用以前存在于其内存位置中的值)。