1

共有ポインタのセットがあります。

共有ポインタが存在するかどうかをチェックする関数を作りたいです。

それを取得するには set.count を使用する必要があると想定しました。

しかし、共有ポインタがそこに存在するにもかかわらず、私は常に 0 を取得します。

私の質問は次のとおりです: count は共有ポインタをどのように比較しますか?

私は C++ の初心者であり、コードを提供することはできますが、その量は多いことを心に留めておいてください。

編集2:建物をチェックして車を追加する機能。

void Garage::addCar(Car& n, Building& m){
    shared_ptr<Building> mm(new Building(m));
    if (this->Buildings.count(mm) == 0){
        cout << m.name << " doesn't exist in " << this->name << "." << endl;
        return;
    }
    shared_ptr<Car> s(new Car(n));
    m.addCar(s);
    Cars.insert(s);
}

建物を作成する機能

 Building Garage::create Building(string name){
    shared_ptr< Building> f_ptr(new  Building(name));
     Buildings.insert(f_ptr);
    return (*f_ptr);
}

クラスガレージ

class Garage {
public:
    Garage(string name);
    ~Garage();
    void admitCar(Car& n, Building& m);
    void dismissCar(Car& n, Building& m);
    void employEmployee(Employee& n, Building& m);
    void dismissEmployee(Employee& n, Building& m);
    Building createBuilding(string name);
    void deleteBuilding(Building&);
    private:
int nextIndex;
    string name;
    set<shared_ptr<Building> > Buildings;
    set<shared_ptr<Employee> > Employees;
    set<shared_ptr<Car> > Car;
}

建物に車を追加しようとすると、その建物はそのガレージに存在しないと表示されます...

解決策(私自身):

bool Garage::hasBuilding(shared_ptr<Building> f){
    return (this->Buildings.count(f) != 0);
}

これは私が作成した関数です。できます。

Jonathan Wakely と LiKao の方法を試してみましたが、私には少し複雑すぎて、やはり自分では解決できない問題がありました。

お手伝いありがとう :)

4

4 に答える 4

3

比較しているポインターは、異なるオブジェクトを指しているため、異なります。new Building古い建物と同じ名前ですが、新しい建物が作成されると言うときはいつでも。したがって、それnew Buildingへのポインターは、新しい建物が作成された元の古い建物へのポインターとは異なります。したがって、比較は正しく、新しい建物はセットに存在しません (コピーして作成したため、存在することはできません)。

ポインターが指すオブジェクトのプロパティに基づいて比較できるセットが必要です。このためには、オブジェクトへのポインターを調べる別の比較関数を追加する必要があります。このようなものが動作するはずです:

struct less_building  : std::binary_function<std::shared_ptr<Building>,std::shared_ptr<Building>,bool> {
  bool operator()( const std::shared_ptr<Building> & b1, const std::shared_ptr<Building> & b2 ) {
    return std::less( b1->name, b2->name );
  }
};

の定義によっては、いくつかの friends 宣言が必要になる場合がありますBuildingが、一般的にはこのような方法でうまくいきます。

注1 :

このトリックを使用する前に、これが意味することを必ず理解してください。このコンパレータを使用するとBuildings、他の属性に関係なく、セット内の 2 つの名前が同じになることはありません。同じ名前を持つ の各ペアはBuilding、後で同じと見なされBuildingます。モデリング ドメインによっては、これが必要な場合とそうでない場合があります。

名前が同じ場合に他の属性も比較したい場合は、これを比較ファンクターに追加する必要があります。Buildingただし、これは、同じ属性セットを持つ が2 つ存在しないことを意味します。繰り返しますが、問題によっては、これが必要な場合とそうでない場合があります。

注2 :

通常、同じタイプのオブジェクトを混在させて参照することは非常に不便でstd::shared_ptrあり、これも経験している問題につながります。任意の場所で型を使用している場合はstd::shared_ptr、一貫性を保ち、これらのみを渡すようにする必要がありますstd::shared_ptr。その理由は、 からstd::shared_ptr参照への変換 (たとえば、 を使用operator*()) は一方向関数によく似ているからです。つまり、 a から参照を取得できますが、参照から を取得するのstd::shared_ptrは非常に困難std::shared_ptrです。一度参照に減衰させた を元に戻すには 2 つの方法が考えられますstd::shared_ptrが、1 つはオブジェクトを変更する必要があり (から派生std::enable_shared_from_this<Building>)、もう 1 つは汚れたコードの非常にひどい臭いがする (新しいオブジェクトを作成する)std::shared_ptr参照のアドレスにノーオペレーションのデリータを使用します)。したがって、どちらの方法もお勧めしません。

代わりに、上記のように、問題のドメインに適合する設計を選択してください。またはstd::shared_ptr腐敗を防ぎます。これらを (const) 参照として渡す場合、std::shared_ptr実際にはポインター自体を渡すだけでなく、コストもそれほどかかりません。

于 2012-06-17T13:18:54.780 に答える
2

あなたの「編集2」に基づいて、私はあなたの誤解を見ていると思います。これらは、まったく関係のない 2 つの共有ポインターです。

Building m;
shared_ptr<Building> a(new Building(m));
shared_ptr<Building> b(new Building(m));

それらは a 内では一致しませんstd::set

ただし、これら関連するポインターです。

Building m;
shared_ptr<Building> a(new Building(m));
shared_ptr<Building> b = a;

したがって、それらは a 内で一致しstd::setます。

基本的に、比較は基になるオブジェクトではなく、ポインターに対して実行されます。

于 2012-06-17T13:13:04.270 に答える
1

あなたの質問に答えるために

count は共有ポインタをどのように比較しますか?

比較はstd::shared_ptrget()メソッドを使用して行われます。つまり、マネージ ポインターが比較されます。に関してstd::set<std::shared_ptr<T>>、関連する比較はbool operator<です。

詳しくはこちらをご覧ください。

于 2012-06-17T13:01:32.087 に答える
1

共有ポインタが存在するかどうかをチェックする関数を作りたいです。

私はあなたがしないと思います。

shared_ptr<Building> mm(new Building(m));
if (this->Buildings.count(mm) == 0){

セット内に作成したばかりの共有ポインタが、作成したばかりの新しいオブジェクトを指しているのに、どうしてそのポインタがセット内に存在できるのでしょmmか? あなたがそれらを作成してからセット内でそれらを探すまでの間に、どのようにしてそれらがセットに入ることができたのでしょうか?

Building建物の値を比較して、その中にa が存在するかどうかを確認したいと思います。特定のオブジェクトまたは特定の共有ポインターがセット内にあるかどうかは気にしません。

mすべての要素が指す建物と比較して、セットを検索することもできます。

void Garage::addCar(Car& n, Building& m){
  bool found = false;
  for (auto& shptr : Buildings)
  {
    if (*sp == m)  // dereference shared_ptr to compare the Building 
    {
      found = true;
      break;
    }
  }

または、この回答のように、セットでカスタム比較を使用します。

于 2012-06-17T13:27:34.970 に答える