にはメソッドQList
がないことに気付きましたが、たとえば、 にはメソッドがあります。どうしてこれなの?また、同等の機能はありますか?resize
QVector
4 に答える
まあ、これはより一般的な答えですが、比較することで、コンテナーを手動で拡張する必要がない理由QList
を理解していただければ幸いです。QVector
QList は内部バッファーを使用して要素へのポインターを保存します (または、要素がポインター サイズよりも小さい場合、または要素が共有クラスの 1 つである場合は要素自体)、実際のデータはヒープに保持されます。
その間、データを削除しても内部バッファーは減少しません (空のスペースは要素を左右にシフトすることで埋められ、後の挿入のために最初と最後にスペースが残されます)。
のようなアイテムQVector
を追加すると、配列の最後に追加の新しいスペースが作成されます。また、 とは異なりQVector
、実際のデータは内部バッファーに格納されないため、アイテムのサイズに関係なく、1 つの命令で多くQVector
のスペースを作成できます ( ) - インデックス バッファにポインタを追加しているだけだからです。
たとえば、32 ビット システム (ポインターごとに 4 バイト) を使用していて、に 50 個のアイテムを格納していてQList
、各アイテムのサイズが 1MB である場合、QVector
バッファーのサイズを 50MB に変更する必要があり、QList
の内部バッファーを割り当てるだけで済みます。 200Bのメモリ。resize()
ここでinを呼び出す必要がありますが、QVector
必要QList
はありません。50MB のメモリを割り当てる場合と同様に、メモリの小さなチャンクを割り当てることは問題ではないためです。
ただし、それには価格があります。つまり、QVector
代わりに優先したい場合があることを意味します。内部バッファが指している)。ポインタより大きい 10000 個のアイテムを追加する場合 (ポインタに収まる場合は内部バッファに直接格納されるため)、ヒープ上の 10000 個のアイテムにデータを割り当てるために 10000 個のシステム コールが必要になります。ただし、 を使用していてを呼び出すと、すべてのアイテムを 1 回の alloc 呼び出しに収めることができます。そのため、大量の挿入または追加が必要な場合は使用しないでください。使っている方はもちろんQList
QList
QVector
resize
QList
QVector
QList
共有クラスを格納するために追加の割り当てを行う必要がないため、これもQList
より適しています。
したがって、QList
ほとんどの場合は次のようにします。
- インデックスを使用して個々の要素にアクセスすると、アイテムへのアクセスがより高速になります。
QLinkedList
- リストの途中に挿入すると、ポインターを移動してスペースを作成するだけで済み、実際の
QVector
データを移動するよりも高速です。 - 空のスペースは後で使用するためにバッファの最後に移動されるため、スペースを手動で予約またはサイズ変更する必要はありません。要素が非常に小さいため、配列内のスペースの割り当ては非常に高速であり、多くのスペースを割り当てることができます。メモリ空間を殺さずにスペースを確保できます。
次のシナリオでは使用しないでくださいQVector
。
- データが連続したメモリ位置に保存されていることを確認する必要がある場合
- ランダムな位置にデータを挿入することはめったになく、最後または最初に大量のデータを追加しているため、多くの不要なシステム コールが発生する可能性があり、それでも高速なインデックス作成が必要な場合。
- 時間が経っても大きくならない単純な配列の (共有) 代替品を探している場合。
そして、最後に注意してください: QList
(and QVector
) には、 が内部バッファーの現在のサイズよりも大きい場合に、の内部バッファーを大きくするreserve(int alloc)
機能があります。ただし、これはの外部サイズには影響しません(リストに含まれる要素の正確な数を常に返します)。QList
alloc
QList
size()
QList
理由は、要素の型にデフォルトのコンストラクターが必要ないためだと思います。この結果、QList
コピーするだけのオブジェクトを作成する操作はありません。
しかし、(何らかの理由で)本当にサイズを変更する必要がある場合はQList
、それを行う関数を次に示します。これは単なる便利な関数であり、パフォーマンスを考慮して書かれていないことに注意してください。
template<class T>
void resizeList(QList<T> & list, int newSize) {
int diff = newSize - list.size();
T t;
if (diff > 0) {
list.reserve(newSize);
while (diff--) list.append(t);
} else if (diff < 0) list.erase(list.end() + diff, list.end());
}
次のようなものを使用するだけです
QList<Smth> myList;
// ... some operations on the list here
myList << QVector<Smth>(desiredNewSize - myList.size()).toList();
基本的に、これらのto
/ from
Vector
/ List
/Set()
メソッドはいたるところにあり、必要に応じて手動で Qt コンテナーのサイズを変更するのは簡単ですが、簡単で効果的な (私が信じている) 方法です。
別の (1 または 2 ライナー) ソリューションは次のようになります。
myList.reserve(newListSize); // note, how we have to reserve manually
std::fill_n(std::back_inserter(myList), desiredNewSize - myList.size(), Smth());
-- これは STL 指向の人々向けです :)
効果がどのように複雑になるかについての背景についてQList::resize()
は、次を参照してください。