次のコードで、VS2010 で奇妙な問題が時々見つかりました。
void Test1()
{
std::vector<int> vec;
vec.push_back(10);
vec.push_back(20);
vec.insert(vec.end(), vec[0]);
// GCC: vec == [10, 20, 10];
// VS2005: vec == [10, 20, 10];
// VS2010: vec == [10, 20, -17891602];
}
vector はメモリを再割り当てし、新しい値を読み取る前に古いメモリを削除するようです。これにより、破損した値がコピーされます。この問題は VS2010 に存在します。VS2005 と GCC でチェックイン - OK。
operator[] または front()/back() メソッドから取得した参照を insert() に渡すことは有効ですか?
UPD:以下のコメントに基づいていくつかの調査を行った結果、パフォーマンスのために reserve() を使用することはお勧めできないという結論に達しました。これは、不要な大量の再割り当てにつながります。
void Test2()
{
std::vector<int> vec, vec2;
const int count = 10000;
int prevCap = 0, reallocCount = 0;
int prevCap2 = 0, reallocCount2 = 0;
for (int i = 0; i < count; ++i)
{
if (vec.size() >= vec.capacity())
{
vec.reserve(vec.size()+1);
}
vec.insert(vec.end(), i);
vec2.insert(vec2.end(), i);
const int cap = vec.capacity();
const int cap2 = vec2.capacity();
if (prevCap != cap) ++reallocCount;
prevCap = cap;
if (prevCap2 != cap2) ++reallocCount2;
prevCap2 = cap2;
}
cout << reallocCount << " " << reallocCount2 << endl;
// reallocCount == 10000, reallocCount2 == 15 GCC
}
したがって、今のところ、次の 2 つのオプションしかありません。
1) 一時変数を使用する
const int tempValue = vec[0];
vec.insert(vec.end(), tempValue);
しかし、いくつかの最適化によってコンパイラが tempValue を削除できるかどうかはわかりません。
2) push_back(0) とさらに pop_back() 呼び出しを使用する
vec.push_back(0);
vec.pop_back();
vec.insert(vec.end(), vec[0]);
VS2005/2010 および GCC で期待される結果とパフォーマンスが得られます。
私は何か見落としてますか?より良い解決策はありますか?