0
votes

Impossible de trouver un type défini par l'utilisateur dans un ensemble C ++ non commandé avec opérateur personnalisé == ()

Déclaration de problème: strong> ITERE sur un tableau d'objets et vérifiez si l'objet existe dans un ONUORDED_SET.

objectif: strong> Je pourrais avoir des milliers d'objets dans un conteneur pour vérifier leur existence chez des millions d'objets dans un autre conteneur. Je choisis une complexité de recherche constante et vecteur pour itération. Je suis nouveau à cela et si vous avez une approche alternative, je l'apprécierais vraiment. P>

problème: strong> Unorded_set Recherche ne fonctionne pas comme prévu ou j'ai eu le concept faux! p>

Main: strong> p> xxx pré>

surcharge de classe de bloc: strong> p>

#pragma once

#include <string>
#include <memory>

using std::string;

class Block {
  private:
    string mName;
    string mLib;
  public:
    Block(string const& name, string const& lib);
    string getName() const;
    string getLib() const;
    bool operator==(std::unique_ptr<Block>& block) const;
};


13 commentaires

quel est le problème? Qu'avez-vous obtenu en tant que sortie? Qu'est-ce que vous attendiez?


S'il vous plaît être si gentille de nous montrer ce que block est et quel type de message d'erreur vous donne le compilateur.


Const comme un argument? Comme dans Bool Block :: opérateur == (const std :: unique_ptr & block) const {


Je n'ai reçu aucun message d'erreur et le code compilé correctement. Mais quand j'ai couru, je n'ai reçu aucune sortie.


Vous bloquez la surcharge de la classe Opérateur == n'a pas d'importance, car les objets du vecteur et de l'ONUNERDED_SET sont des pointeurs intelligents. Le code comparait les pointeurs intelligents, pas les objets de blocs.


Vous comparez des pointeurs avec des pointeurs qui appartiennent à des adresses. Block JAMAIS ENTRÉE JAMAIS JEURE ICI SO Bloc :: Opérateur == n'est pas considéré. Et puisque Recherche ne prend que unique_ptr SO Il ne peut pas être fait pour fonctionner comme vous le souhaitez. Utilisez std :: recherche_if à la place.


Tout le monde peut bloquer-> getname () être appelé sur std :: unique_ptr & block qui est la valeur non Const?


@RIXMENT • Les méthodes constantes peuvent être appelées des objets non constitutifs. Mais pas vice versa: Impossible d'appeler une méthode de non-Const sur un objet Const.


Lorsque vous définissez l'opérateur surchargé sous forme de méthode, il sera utilisé uniquement lorsque l'objet de cette classe sur le côté gauche, et non le pointeur non intelligent. Vous avez besoin d'une fonction autonome qui accepte 2 instances de std :: unique_ptr


Quelle est la solution alors? Global opérateur == (std :: unique_ptr &, std :: unique_ptr &) ? Ou opérateur == (bloc et, bloc et) suffira avec une conversion implicite de std :: unique_ptr à bloc ?


Ok, une question suivante: trouvera-t-il un impact sur la performance / la complexité si mon upommande_set contient un million d'objets? [En outre, j'apprécie vraiment tous les commentaires, merci.]


@Sourabshama, peu importe la façon dont vous faites cela, vous devrez inspecter la valeur que vos indicateurs pointent. Cela sera probablement un peu plus lent que de comparer des adresses, mais c'est nécessaire. Que ce soit via Find_IF ou un autre schéma ne fera pas une grande différence. Donc, ce n'est pas wind_if qui aura intrinsèquement la performance touchée.


Je viens d'ajouter l'objectif. Tout commentaire de @all à ce sujet. Merci


3 Réponses :


2
votes

Un Unommked_set nécessite une fonction de hachage et une fonction de comparaison. Vous utilisez les fonctions de hachage et de comparaison existantes pour std :: unique_ptr , ce qui n'est certainement pas ce que vous voulez.

Je ne suggérerais pas d'essayer de changer le comportement de std :: unique_ptr car cela conduira à la confusion dans un autre code qui veut une sémantique normale pour les pointeurs. Au lieu de cela, ajoutez des fonctions de hachage et de comparaison normales pour bloc et transmettez des personnalisés sur le constructeur du non ordonnée_sed_sed . .


3 commentaires

Merci. J'ai compris le problème. Tout commentaire sur la partie de but?


J'éviterais juste std :: vecteur sauf si vous pouvez la taille de bonne forme avant toutes les insertions (avec réserve ). Sinon, utilisez std :: list .


D'accord. Merci David.



2
votes

Vous essayez de comparer les pointeurs, pas les valeurs. Vous devez spécifier la fonction de hachage pour la classe bloquer code>.

Par exemple, si vous souhaitez utiliser MNAME comme clé, le code sera le suivant: p>

class Block {
private:
    string mName;
    string mLib;
public:
    Block(string const& name, string const& lib)
    {
        mName = name;
        mLib = lib;
    }
    string getName() const {
        return mName;
    };
    string getLib() const {
        return mLib;
    }
    bool operator==(const Block & block) const;
};

template<> struct std::hash<Block> {
    std::size_t operator()(const Block & block) const noexcept {
        return std::hash<std::string>{}(block.getName());
    }
};

bool Block::operator==(const Block & block) const {
    return block.getName() == mName;
}

int main() {
    std::vector<Block> vertices;

    vertices.emplace_back(Block("mod1", "work"));
    vertices.emplace_back(Block("mod2", "work"));
    vertices.emplace_back(Block("mod3", "work"));

    std::unordered_set<Block> undefs;
    undefs.emplace(Block("mod1", "work"));
    undefs.emplace(Block("mod2", "work"));

    for (auto& vertex : vertices) {
        auto search = undefs.find(vertex);
        if (search != undefs.end()) {
            std::cout << "Block: " << vertex.getName() << "\n";
        }
    }
}


4 commentaires

Merci. J'ai compris le problème. Ma seule préoccupation consiste à stocker des objets directement par rapport à la conservation des pointeurs qui leur dirigent. Comme je l'ai expliqué dans le but, je traite un grand nombre d'objets ici et la performance est ma priorité principale.


@Sourab Sharma, si la performance est importante, je vous suggère d'utiliser hachage en interne: vous pouvez calculer le hachage pour le MNAME (par exemple) et l'utiliser comme une clé de votre objet. Si vous allez opérer principalement avec ces hachages et non les noms, ce sera beaucoup plus rapide que les cordes de hachage à chaque fois. Ceci est parfois appelé "inlinage à cordes", mais parfois cela signifie des arbres préfixaux, pas de hachage. Pour la plupart des cas, le hachage est optimal, surtout si vous n'avez pas de collision


WHOOPS, je veux dire "string interne", pas d'inlinage :) Je vous recommande également de lire le livre "Architecture du moteur de jeu" qui décrit de nombreuses optimisations de ce type en termes de performances.


Je pense que j'ai maintenant assez de choses pour essayer de travailler avec. Merci encore. Et je vais vérifier le livre aussi.



0
votes

Le problème est que vous essayez de comparer les pointeurs, qui sont différents! Je sauverais les raisons de l'utilisation de l'unique_ptr <> mais en faisant que vous essayez réellement de comparer des identités, au lieu d'états qui sont ce que vous voulez.

Vous pouvez donc voir ce que je veux dire, disons que le premier objet de bloc est en position 100 dans votre mémoire. Ce serait son identité. Nous avons donc des objets1 dont l'état est "mod1, travail" et dont l'identité est 100. Nous avons l'objet2, dont l'identité est de 150 mais son état est identique à l'objet1, "mod1, travail".

Tout ce que vous avez à la fois à l'intérieur du vecteur et que les pointeurs sont des pointeurs, vous avez donc des positions de mémoire. Lorsque vous les insérez dans le vecteur, vous avez inséré, disons, positionnez 100. Mais dans le non-ordonné vous inséré 150. Ils ont le même état, mais la méthode de recherche est à la recherche d'une position de mémoire.

J'espère que ma réponse a été utile. Si vous trouvez des erreurs ici ou pensez différemment s'il vous plaît faites le moi savoir. Bonne chance! :)


4 commentaires

J'ai compris votre point (très empathétiquement expliqué, merci) mais si je dois créer des millions d'objets sur la pile et les stocker dans un conteneur, ce ne sera-t-il pas un problème par rapport à la conservation des pointeurs?


@Sourabsharma une pile construite sur std :: Liste stocke les pointeurs des objets déjà. Il suffit de ne pas construire sur std :: vecteur .


@Sourabsharma Qu'entendez-vous sur la pile? Si vous utilisez std :: vecteur / Toute autre données de conteneurs est en cours d'enregistrement sur le tas en utilisant Nouveau interne (pour être précis, ceci est défini par allocator). Il est très peu susceptible de vouloir stocker des millions d'objets sur la pile. Habituellement, la pile ne dépasse pas 10 Mo.


@espkk ok je n'étais pas au courant de cela.