1

だから、私はboost :: arrayを見てきましたが、デフォルトのコンストラクターが定義されている必要があります。この配列をデータで埋める最良の方法は、push_back(const T&)メソッドを使用することだと思います。SIZE(コンパイル時に認識される)よりも多く呼び出すと、ビルド構成に応じて、アサートまたは例外が発生します。このようにすると、常に意味のあるデータが含まれます。この概念の効率的で、移植性があり、信頼できる実装を知っている人はいますか?

4

5 に答える 5

1

さて、誰かが今答えを持ってきたのではないかと思っていたのですが、そうではないようですので、行きましょう。

あなたが望んでいるのは、私自身が夢見てきたことですboost::optional_array<T,N>

2つのバリエーションがあります。

  • まず、と同様にboost::array< boost::optional<T>, N >、各要素が設定される場合とされない場合があります。
  • 2番目:(std::vector<T>どういうわけか)と同様に、すべての開始要素が設定され、後続のすべての要素は設定されません。

前の質問/コメントを考えると、2番目が欲しいようですが、どちらも非常に似ているので、実際には問題ではありません。

template <typename T, size_t N>
class stack_vector
{
public:
  bool empty() const { return mSize == 0; }
  size_t size() const { return mSize; }
  size_t capacity() const { return N; }
  size_t max_size() const { return N; }

  T& operator[](size_t i) { return *(this->pfront() + i); }
  /// ...

private:
  T* pfront() const { return reinterpret_cast<T*>(&mStorage); }

  std::aligned_storage< N * sizeof(T), alignof(T) > mStorage;
  size_t mSize; // indicate how many elements are set, from the beginning
};

これらの非常に特殊な操作に焦点を当てましょう。

template <typename T, size_t N>
void push_back(T const& t)
{
  new (this->pfront() + mSize) T(t); // in place construction
  ++mSize;
}

template <typename T, size_t N>
void clear()
{
  for (size_t i = 0; i != mSize; ++i)
  {
    (this->pfront() + i)->~T();
  }
  mSize = 0;
}

お気づきのように、主な難しさは次のことを覚えておくことです。

  • まだ要素が構築されていない場合は、割り当てではなく、配置新規+コピー構築が必要です。
  • 「廃止」された(つまり、最後の要素の後にある)要素は、適切に破棄する必要があります(つまり、それらのデストラクタが呼び出されます)。

従来のSTLコンテナには、実装が難しい可能性のある多くの操作があります。でvector、要素のシャッフル(insertまたはによるerase)はおそらく最も印象的な例です。

また、C ++ 0xと初期化リストvectorを使用emplace_backすると、要素を適切に直接構築できるため、CopyConstructible要件が解除されるため、ケースによっては便利な場合があります。

于 2010-10-07T06:28:20.550 に答える
0

boost::array<T, 12> ta;と違いはありませんT[12] ta;; 初期化子リストを使用しない場合、要素はデフォルトで作成されます。

一般的な回避策は、boost::array<T*, 12> ta;または多分boost::array<unique_ptr<T>, 12> ta;です。

値で保存する唯一の方法はコピーすることであり、それを回避する方法はありません...これは初期化リストが行うことです。

struct A {
    A(int i):_i(i){ cout << "A(int)" << endl; }
    A(const A& a){ cout << "A(const A&)" << endl; }
    ~A(){ cout << "~A()" << endl; }

    int _i;
};

int main(){
    boost::array<A, 2> ta = {{1, 2}};
}

これは以下を出力します:

A(int)
A(const A&)
A(int)
A(const A&)
~A()
~A()
~A()
~A()

http://codepad.org/vJgeQWk5

于 2010-10-06T14:51:25.330 に答える
0

ブースト::アレイにブースト::バリアントを格納できますか? 最初のパラメーターを int などにします。

すなわち

boost::array<boost::variant<int, foo>, 6> bar;

バリアントに対処する必要がありますが、スタックが割り当てられています...

于 2010-10-06T15:48:24.997 に答える
-1

C ++ 0xではstd::array<type, size>(おそらくboost :: arrayと同じです)。fill()またはを使用して配列データを初期化できますstd::fill_n()

std::array<int, 30> array;
array.fill(0);
boost::array<int, 30> barray;
std::fill_n(barray.begin(), 30, 0);

定義時にデフォルトで初期化する場合は、copy-ctorを使用できます。

static std::array<int, 30> const nullarray = {0, 0, 0, ..., 0}; // nullarray.fill(0);
// (...)
std::array<int, 30> array{nullarray};
于 2010-10-06T14:50:03.057 に答える
-1

なぜスタックに常駐する必要があるのですか? reservea の作成と ingvectorが遅すぎるという経験的証拠はありますか( a を使用するvectorのは明らかな答えのようです)。

その場合でも、スペースが予約されているベクトルのプールとswap、事前に割り当てられたベクトルの 1 つをローカル コピーに作成できます。ローカルのものを使い終わったら、元に戻します (s のspliceトリックと同じようにlist)。

于 2010-10-06T15:18:08.800 に答える