にほ さんが書きました:
このようなコードを実行すると、数回は成功するのですが、途中で以下のような例外が発生します。
std::vector<std::shared_ptr<Object>,std::allocator<std::shared_ptr<Object> > >::operator[](...)._Ptr-> が 0xB5B8 でした。
最初の数回は期待通りの実行結果が得られるので、関数自体にアクセスすることは可能なのですが、その後アクセスできなくなっているようです。原因がわかる方、どなたかご教授いただければ幸いです。
Frame::Update や Field::Update がどうなっているのかの記述がないので、
SceneGame::obj がどんなふうに破壊されているのかが分かりません。
提示されたコードから分かることは、
SceneGame のコンストラクタの sort が間違っていることです。
sort(obj.begin(), obj.end()); で obj をソートしようとしていますが、
obj は shared_ptr の vector なので、ポインタの大小でソートされます。
ポインタが指す Object (Frame または Field) を priority でソートしたいらしくて、
Object の中で operator() を定義していますが、それは使われません。
次のように書けば、Object::operator() が呼び出されて、
priority でソートされます。
コード:
sort(obj.begin(), obj.end(),
[](shared_ptr<Object>& a, shared_ptr<Object>& b) { return (*a)(a, b); }
);
でも、operator() が Object のメンバ関数というのは変ですよね。
メンバ関数は、メンバ変数を参照したり変更するためにあります。
自身のメンバ変数は参照せず、引数で与えられた 2つのオブジェクトの比較を
だけを行うとはどういうことでしょうか?
どうしてもこのメンバ関数を使うのならということで、(*a)(a, b) のようにしました。
また Object::operator()関数の引数の型を const shared_ptr<Object> にして
いますね。これだと、呼び出し時に shared_ptr のコピーが起こり、
shared_ptr の持っている参照カウントが 1 増えます。
関数を出るときは、参照カウントが 1 減ります。これらの余計な処理を
しないで済むように、参照 const shared_ptr<Object>& にしましょう。
メンバ関数で実現しようとすれば、
コード:
bool operator() (const shared_ptr<Object>& right) const {
return this->priority < right->priority;
}
コード:
sort(obj.begin(), obj.end(),
[](shared_ptr<Object>& a, shared_ptr<Object>& b) { return (*a)(b); }
);
または、
コード:
bool operator<(const Object& right) const {
return tpriority < right.priority;
}
コード:
sort(obj.begin(), obj.end(),
[](shared_ptr<Object>& a, shared_ptr<Object>& b) { return *a < *b; }
);
外部関数にしてしまってもいいでしょう。
コード:
bool lt(const shared_ptr<Object>& left, const shared_ptr<Object>& right) {
return left->priority < right->priority;
}
コード:
sort(obj.begin(), obj.end(),
[](shared_ptr<Object>& a, shared_ptr<Object>& b) { return lt(a, b); }
);
ただし、protectd の priority にアクセスできないので、class Object の中に
friend bool lt(const shared_ptr<Object>& left, const shared_ptr<Object>& right);
が必要です。