5

これは未定義の動作ですか?

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";
}

はいかもしれませんが、sをスライスする安全な方法があるはずだと本当に感じていますstd::array

編集: 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]);
}

編集:わかりました、私はstd::arraysに不満があると判断し、他の何かに移動します、何かアイデアはありますか?

4

2 に答える 2

6

はい、それは未定義の動作です。あなたはあるタイプを取り、reinterpret_castそれを別のタイプに変えています。確かに、の使用はreinterpret_cast「ここにドラゴンがいる!」の大きな赤い旗になるはずです。

アレイのスライスに関しては、それは起こりません。Astd::arrayには値が含まれます。このスライスには、その配列の一部への参照が含まれます。したがって、それはではありませんstd::array。配列のスライスをコピーできますが、を使用することはできませんstd::arraystd::vectorコンストラクターの呼び出しと、値の範囲からの構築が可能になるため、を使用する必要があります。覚えておいてください:std::arrayCスタイルの配列のより良いラッパーです。

委員会はテンプレートarray_ref<T>クラスを調査しています。これはまさにそれが言っていることです。タイプの配列のあるセグメントへの参照Tです。これは、通常のCスタイルの配列、、、、std::vectorまたはstd::arrayで割り当てられたメモリの場合がありnew T[]ます。このクラスにはすでにいくつかのライブラリ実装がありますが、まだ標準化されているものはありません。


Radekの提案に従って:

関数で未定義の動作を非表示にしても、定義された動作にはなりません。未定義ではないふりをすることができますが、それでも未定義です。あなたがそれを使う瞬間reinterpret_cast、あなたは喜んでC++ランドでの生活をあきらめます。

于 2012-05-25T20:12:29.663 に答える
-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," "));
}
于 2014-07-06T15:53:28.790 に答える