30

データを新しい std::array にコピーせずに、C スタイルの配列を std::array として扱う安全で標準に準拠した方法はありますか?

これは明らかにコンパイルされませんが、私が望む効果です (私の実際の使用はもっと複雑ですが、この短いサンプルは私がやりたいことを示しているはずです)。reinterpret_cast は「機能する」と思いますが、おそらく安全ではありませんか?

#include <array>

int main()
{
    int data[] = {1, 2, 3, 4, 5};

    // This next line is the important one, treating an existing array as a std::array
    std::array<int, 5>& a = data;
}

データは同じように保存する必要があるため、可能であるべきだと感じています。

編集:明確にするために、新しい std::array をクリアしたくないので、既存のデータを 1 つとして参照したいと思います。

4

3 に答える 3

26

この投稿で説明され ているように、T が POD の場合、std::array<T, S> は POD であることが保証されていますか?

std::array<int, N>POD であるため、標準レイアウトです。標準のレイアウト要件を理解している限り、これは、オブジェクトへのポインターが最初のメンバーへのポインターと同じであることを意味します。std::array にはプライベート/保護されたメンバーがないため ( http://en.cppreference.com/w/cpp/container/arrayによると)、これはラップされた配列の最初の要素と一致する必要があります。したがって、次のようなもの

reinterpret_cast< std::array<int, 5>* >( &data )

私の意見では、標準で動作することが保証されています。ただし、標準語を解釈するのが難しい場合があることを認めなければならないので、間違っている場合は訂正してください。

よろしくクラース

于 2013-01-29T08:21:21.297 に答える
12

それをしてはいけない。はstd::array集約であり、独自のデータ ブロックを保持します (簡単に再割り当てできるデータ ブロックへのポインターとは対照的です)。したがって、すべての要素のコピーを回避する方法はありません。C++11 では、配列のデータを移動できないため、これは特に重要ですstd::swap。たとえば、効率的な関数はありません。

于 2012-06-26T10:21:25.457 に答える
12

reinterpret_castを使用できますが、これは醜い汚いハックであり、実際のリリース コードで次のようなことを行うべきではないことに注意してください。

std::array<int, 5> &a = reinterpret_cast<std::array<int, 5>&>(data);

std::arrayの内部実装が変更された場合、問題が発生する可能性があります (たとえば、STL のデバッグ バージョンにいくつかの追加フィールドが追加され、いくつかの実行時チェックが行われます)。次に、このコードは有益なメッセージなしでクラッシュを開始します (これは、std::array オブジェクトと C 配列が同じメモリ レイアウトを持つという暗黙の仮定に基づいているためです)。

それでも醜い汚いハックに行くことにした場合は、少なくともコンパイル時のサイズチェックを追加してください。

    C_ASSERT(sizeof(a) == sizeof(data));

これにより、std::array<> のサイズが C 配列のサイズと一致しなくなった場合にエラーが発生します (STL 実装の変更により)。

于 2012-06-26T10:24:38.157 に答える