Funzione di confronto delle stringhe STL
Domanda
Ho il seguente funzione:
class ComparatorClass {
public:
bool operator () (SimulatedDiskFile * file_1, SimulatedDiskFile * file_2) {
string file_1_name = file_1->getFileName();
string file_2_name = file_2->getFileName();
cout << file_1_name << " and " << file_2_name << ": ";
if (file_1_name < file_2_name) {
cout << "true" << endl;
return true;
}
else {
cout << "false" << endl;
return false;
}
}
};
Dovrebbe essere un ordinamento rigorosamente debole, ed è così lungo (potrebbe essere solo una riga) per scopi di debug.
Sto usando questo functor come funzione di confronto per uno stl :: set. Il problema è che inserisce solo il primo elemento. Aggiungendo l'output della console alla funzione di confronto, ho appreso che sta effettivamente confrontando il nome del file con se stesso ogni volta .
Altre righe pertinenti sono:
typedef set<SimulatedDiskFile *, ComparatorClass> FileSet;
e
// (FileSet files_;) <- SimulatedDisk private class member
void SimulatedDisk::addFile(SimulatedDiskFile * file) {
files_.insert(file);
positions_calculated_ = false;
}
EDIT: il codice che chiama .addFile () è:
current_request = all_requests.begin();
while (current_request != all_requests.end()) {
SimulatedDiskFile temp_file(current_request->getFileName(), current_request->getResponseSize());
disk.addFile(&temp_file);
current_request++;
}
Dove all_requests è un elenco e la classe Request è tale che:
class Request {
private:
string file_name_;
int response_code_;
int response_size_;
public:
void setFileName(string file_name);
string getFileName();
void setResponseCode(int response_code);
int getResponseCode();
void setResponseSize(int response_size);
int getResponseSize();
};
Vorrei poter offrire la mia ipotesi su cosa sta succedendo, ma in realtà non ne ho idea. Grazie in anticipo per eventuali suggerimenti.
Soluzione
Non c'è niente di sbagliato nel codice che hai pubblicato, funzionalmente parlando. Ecco un programma di test completo: ho solo riempito gli spazi vuoti, senza cambiare affatto il tuo codice.
#include <iostream>
#include <string>
#include <set>
using namespace std;
class SimulatedDiskFile
{
public:
string getFileName() { return name; }
SimulatedDiskFile(const string &n)
: name(n) { }
string name;
};
class ComparatorClass {
public:
bool operator () (SimulatedDiskFile * file_1, SimulatedDiskFile * file_2) {
string file_1_name = file_1->getFileName();
string file_2_name = file_2->getFileName();
cout << file_1_name << " and " << file_2_name << ": ";
if (file_1_name < file_2_name) {
cout << "true" << endl;
return true;
}
else {
cout << "false" << endl;
return false;
}
}
};
typedef set<SimulatedDiskFile *, ComparatorClass> FileSet;
int main()
{
FileSet files;
files.insert(new SimulatedDiskFile("a"));
files.insert(new SimulatedDiskFile("z"));
files.insert(new SimulatedDiskFile("m"));
FileSet::iterator f;
for (f = files.begin(); f != files.end(); f++)
cout << (*f)->name << std::endl;
return 0;
}
Ottengo questo output:
z and a: false
a and z: true
z and a: false
m and a: false
m and z: true
z and m: false
a and m: true
m and a: false
a
m
z
Nota che il set finisce con tutte e tre le cose memorizzate al suo interno e la tua registrazione comparativa mostra un comportamento ragionevole.
Modifica
Il tuo bug è in queste righe:
SimulatedDiskFile temp_file(current_request->getFileName(), current_request->getResponseSize());
disk.addFile(&temp_file);
Stai prendendo l'indirizzo di un oggetto locale. Ogni volta attorno al ciclo quell'oggetto viene distrutto e l'oggetto successivo viene allocato esattamente nello stesso spazio. Quindi alla fine del ciclo esiste ancora solo l'oggetto finale e hai aggiunto più puntatori allo stesso oggetto. Al di fuori del ciclo, tutte le scommesse sono disattivate perché ora non esiste alcun oggetto.
O alloca ogni SimulatedDiskFile con new (come nel mio test, ma poi dovrai capire quando eliminarli), oppure non usare affatto i puntatori (molto più facile se si adatta ai vincoli del tuo problema ).
Altri suggerimenti
Ed ecco il problema:
SimulatedDiskFile temp_file(current_request->getFileName(),
current_request->getResponseSize());
disk.addFile(&temp_file);
Stai aggiungendo un puntatore a una variabile che viene immediatamente distrutta. Devi creare dinamicamente i tuoi oggetti SDF.
urrent_request = all_requests.begin();
while (current_request != all_requests.end()) {
SimulatedDiskFile temp_file(...blah..blah..); ====> pointer to local variable is inserted
disk.addFile(&temp_file);
current_request++;
}
temp_file andrebbe fuori ambito al momento della successiva iterazione nel ciclo while. È necessario modificare il codice di inserimento. Crea oggetti SimulatedDiskFile sull'heap e spingi diversamente se gli oggetti sono più piccoli, quindi archivia per valore nel set.
Accetto con @Earwicker. Tutto sembra a posto. Hai dato un'occhiata all'interno di all_requests? Forse tutti i nomi dei file sono uguali lì dentro e tutto il resto funziona bene? (sto solo pensando ad alta voce qui)