我可以将std :: array转换为切片吗?或者还有什么我可以使用的吗?

Gio*_*hal 4 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";
}
Run Code Online (Sandbox Code Playgroud)

也许是的,但我真的觉得应该有一个安全的方法来切片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]);
}
Run Code Online (Sandbox Code Playgroud)

编辑:好的,我决定我对std::arrays 不满意,并会转向其他任何想法?

Nic*_*las 6

是的,这是未定义的行为.你正在采用一种类型并将reinterpret_cast其转换为另一种类型.事实上,使用该reinterpret_cast应该是"这里有龙!"的一个大红旗!

至于切片阵列,这不会发生.A std::array包含值; 其中的一部分将包含对该数组的一部分的引用.因此,它不会是一个std::array.您可以复制数组切片,但不能使用std::array.您需要使用std::vector,因为它允许调用构造函数,以及从一系列值构造.请记住:std::array只是围绕C风格数组的更好的包装器.

委员会正在研究一个模板array_ref<T>类,它正是它所说的:对类型数组的某些段的引用T.这可能是一个常规的C风格数组,a std::vector,a std::array,或只是分配的一些内存new T[].该类已经一些库实现,但还没有标准化.


根据拉德克的建议:

隐藏函数的未定义行为不会使其定义行为.您可以尝试假装它没有未定义,但它仍然是.你使用它的那一刻reinterpret_cast,你愿意放弃在C++生活 - 土地.

  • @Giovanni:"C数组完全有效的东西对C++无效"不,不是.当那些数组*衰减成指针时,它只对C数组"有效".此时他们不再是*数组*; 他们是指针.你不能把`int [5]`变成`int [3]`; 你可以将它变成一个`int*`,但这是一个不同的结构.`std :: array`的作用是将衰减删除为指针,以便数组*始终保持*数组(除非你明确地衰减它们,此时你愿意放弃安全).这就是`array_ref`的全部内容. (4认同)
  • @Giovanni:这个讨论是关于C++ 11,而不是C99.在C++ 11中,从`int [5]`到`int [3]`的转换是*未定义的行为*. (3认同)
  • @Giovanni:只有当你试图将它用于不适合用的东西时,它才被打破.这就像说`std :: list`被破坏了,因为它的元素没有连续存储,或者`std :: map`被破坏,因为它不提供O(1)查找.你期待锤子起到螺丝刀的作用. (2认同)
  • @GiovanniFunchal您是否引用了6.5.6加法运算符?如果是这样,这不支持从`int [5]`到`int [3]`的转换在C99中定义良好. (2认同)

Sol*_*kar -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," "));
}
Run Code Online (Sandbox Code Playgroud)