0

次のようなシナリオがあります。

#include <algorithm>
using namespace std;

// a "heavy" struct with lots of members
struct B {
  int key;
  // other members  
} 

class A {
  vector<B> bs;
}

bsをキーでソートしたい。さて、B の交換を避けるために過去にこれを行った方法は (かなり重いため)、インデックスのベクトルを定義し、代わりにインデックスをソートすることです。これは、bs がクラス メンバーでない場合に機能します。

例えば

vector<B> bs;
vector<size_t> indices;

bool pred(size_t i, size_t j) { return bs[i] < bs[j]; }

indices.resize(bs.size());
for (size_t i = 0; i < bs.size(); i++) indices[i] = i;
std::sort(indices.begin(), indices.end(), pred);

ただし、bs がクラス メンバーの場合、述語は 2 つのパラメーターしかとれないため、この「手法」は失敗します。特に、「これ」を渡す方法はありません。

この問題を解決するには、次の 3 つの方法があります。

  • インデックスを気にしないでください。Bのインスタンスを処理するために演算子をオーバーロードするだけ<です。このインデックス全体は時期尚早の最適化です:-)
  • へのグローバル ポインタをbs用意し、 を呼び出す前に設定しsort、 で使用しpredます。
  • クロージャーを使用します。私が C++11 を使用していないことを除けば、これはかなりクールです。

これを行う他の方法はありますか?ありがとう!

4

2 に答える 2

1

軽量スワップを作成できる場合B、問題は実際には存在しませんsort。軽量スワップを使用します。

それがオプションでない場合は、クラスへの (スマート) ポインターをベクターに格納し、ポインターを並べ替えることができます。

または、クラスで pimpl イディオムを使用してから、ほとんど無料で交換します。

グローバル ポインターは絶対に使用しないでください。このコードをスレッドセーフにしたい場合があり、ソートに使用されるグローバル コンテナーは、これらのオブジェクトのマルチスレッド ソートを試みる際に大きな問題になるためです。

于 2012-06-27T05:08:58.593 に答える
1

bが にclass Aあり、 というメンバー関数を介してアクセスできると仮定するとget、次のようなファンクターを作成できます。

struct Comparator
{
  Compartor(A& a): m_a(a){}
  bool operator()(int i, int j) const
  {
    return m_a.get(i) < m_a.get(j);
  }

 A& m_a;
};

そして、次のように使用します。

A a;
std::sort(indices.begin(), indices.end(), Comparator(a));
于 2012-06-27T05:10:04.807 に答える