2017-03-19 7 views
2

を変換しない私は、cppのアプリに(おおよそ)このコードを持っている:はなぜSTDのこの使用は::原因EXC_BAD_ACCESS

QList<Foo> rawAssets = getlist(); 
QVector<std::pair<QString, QString>> assets; 
std::transform(rawAssets.begin(), rawAssets.end(), assets.begin(), makePair); 

私は再びassetsを使用するときにスローするexc_bad_accessの原因となります。

しかし、assets.begin()std::back_inserter(assets)に変更すると、期待どおりに機能します。

std::transformのチュートリアルでは、両方の使用法が示されています。私の場合、なぜそれは間違っているのですか?

答えて

3

QVector<std::pair<QString, QString>> assetsと宣言しました。それはです。したがって、assets.begin()assets.end()に等しく、空のベクトルの最後を指します。

std::transformの3番目のパラメータはtransform変換の結果を書き込む(各書き込み後にインクリメント)なる介しイテレータです。

assets.begin()を渡すと、transformは、この過去エンドイテレータを介して書き込みを行い、結果として範囲外の書き込みが発生します。このようなことを大まかにchar x[3]; x[4] = 'a';

あなたはstd::back_inserter(assets)に渡すと、あなたは特別なイテレータを作成をしているのと同じですassetsにそれを介して、実際に挿入書かれた要素を書きます。だからすべてが順調です。

assetsが既に十分なサイズで、にその要素を上書きしたい場合は、最初の形式を使用することができます。 2番目の形式は、assetsに変換したいときに使用します。

+0

したがって、assets.begin()はassets.end()と等しく、これは欠けていた部分です。ありがとうございました! – Daenyth

0

std::transform()は出力に直接書き込むことができると仮定しています。あなたの場合、ゼロサイズのベクトルです。ベクトルをトランスフォーム入力のサイズに明示的にリサイズするか、既に発見した通りback_inserterを使用してバグを修正できます。

0

assetsのサイズをrawAssetsと同じサイズに変更した場合は、transformの前にはアクセスできません。 back_insert_iteratorを使用すると、transformの各イテレータに対してpush_backが呼び出されます。それがなければ、それはまだ空であるassetsの第1、第2、第3などの要素にアクセスしようとします。したがって、不正なアクセスが発生します。

1

assetsは、空のベクトルとして開始します。

transform()の3番目のパラメータは出力イテレータです。あなたのコードは次のように本質的に等価である:

QVector<std::pair<QString, QString>> assets; 

auto output_iter=assets.begin(); 

// You now call transform(), passing output_iter 
// 
// transform() then essentially does the following: 

*output_iter++ = /* first transform()ed value */; 
*output_iter++ = /* second transform()ed value */; 

// ... and so on. 

方法transform()作品だこと。 assets()は空のベクトルなので、begin()は終了イテレータの値を返します。そして、コードは優雅にベクトルの終わりを越えて書いて行きます。そうtransform()は、事前にサイズ変更配列の内容を記入してしまい、

  1. begin()イテレータを取得する前に、resize()あなたがtransform()しようとしている要素の数にベクトル:

    は、次の2つの基本的なオプションを持っています、正確に。しかし、あなたのデータはリストから来ているので、簡単には入手できません:

  2. 空の配列のイテレータの代わりにstd::back_insert_iteratorからtransform()を渡してください。

関連する問題