ベクトルのサイズ変更-ポータブルな検出方法
-
03-07-2019 - |
質問
既知の量の要素(N)を読み込んでいるベクトルがあります。
処理により、新しい要素が動的に作成され、ベクターに追加されます。
約2 * N個の追加要素が作成されると予想していますが、 したがって、ベクトルのサイズを3 * Nに変更します。
追加の要素がそれを超える場合、ベクトルの動的な展開ではなく、プログラムの中止を希望します。
それを検出する方法はありますか?AIX / TRU64 / Linux間で移植可能ですか?
解決
何を検出しますか?ベクターのサイズを変更するかどうか?それがあったかどうか
これを達成する唯一の実際の方法は、カスタムアロケーターまたはベクターに要素を追加する関数のいずれかでチェック機能を提供することです。
e.g
template<class T>
void add_element(std::vector<T>& container, T const& v)
{
if (container.capacity()+1 >= 3*N)
{
// terminate/exception/whatever
}
container.push_back(v);
}
他のヒント
なぜベクターを使用しているのですか?ベクトルのポイントは、必要なときに動的に拡張することです。
ベクターに委任するクラスを作成する代わりに、単純な配列に委任するクラスを作成します。 push_backでサイズを確認し、必要に応じて中止してください。
ベクターに委任する独自のクラスを作成します。そして、独自のpush_backでサイズを確認します。
コンパイル時にサイズがわかっている場合は、std :: tr1 :: array(または boost :: array )をお勧めします。固定サイズを保持し、std :: vectorのようなアクセスをチェックします。
ただし、ここで他の人が言ったように、実行時にしかわからない場合は、必要な条件をチェックする特定の関数を持つクラスにベクトルをカプセル化する必要があります(アサーションなどを使用)。
この最後のアプローチでは、ベクトル作成時の最大サイズがわかっている場合は、カプセル化クラスコンストラクターでベクトルの最大サイズを予約(またはstd :: vector :: reserve())することをお勧めします(または初期化関数)。これにより、ベクター自体によるメモリ操作はなくなります(ベクター要素のコンストラクター/デストラクターがそのような操作を行う場合のみ)。次に、クラスのすべての関数の開始時と終了時にベクトル容量(std :: vector :: capacity())が変更されないことをチェックする単純なアサーションを追加すると、メモリが移動しないことを確認できます。
たとえば(DATA_MAX_SIZEがどこかで定義されたデフォルトの最大サイズであると仮定します):
template< typename MyType >
class MyData
{
public:
MyData( unsigned long max_size = DATA_MAX_SIZE )
: m_max_size( max_size )
{ m_data.reserve( m_max_size ); }
void add( const MyType& value ) { check_capacity(); m_data.push_back( value ); check_capacity(); }
private:
std::vector< MyType > m_data;
const unsigned long m_max_size;
void check_capacity() { if( m_data.capacity() != m_max_size ) throw Exception("Useful error message here!" ); }
};
またはそのようなもの...
stdクラスは、要素を挿入するたびに呼び出されるアロケーターを使用します。 std :: alocatorを継承する新しいアロケーターを作成し、必要なすべての種類のチェック/トレースを追加できます。
(以前にこれを実行しましたが、動作するコードを作成するのに時間がかかりました。)