Вопрос

У меня есть следующий функтор:

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;
      }
    }
};

Предполагается, что это строгий слабый порядок, и он такой длинный (может быть только одна строка) для целей отладки.

Я использую этот функтор в качестве функтора компаратора для stl::set.Проблема в том, что он вставляет только первый элемент.Добавив консольный вывод в функцию comparator, я узнал, что на самом деле она сравнивает имя файла с самим собой каждый раз, когда.

Другими релевантными строками являются:

typedef set<SimulatedDiskFile *, ComparatorClass> FileSet;

и

// (FileSet files_;) <- SimulatedDisk private class member
void SimulatedDisk::addFile(SimulatedDiskFile * file) {
  files_.insert(file);
  positions_calculated_ = false;
}

Редактировать: код, который вызывает .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++;
}

Где all_requests - это список, а class Request таков, что:

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();
};

Хотел бы я предложить свою гипотезу относительно того, что происходит, но на самом деле я понятия не имею.Заранее спасибо за любые указания.

Это было полезно?

Решение

С функциональной точки зрения в опубликованном вами коде нет ничего плохого.Вот полная тестовая программа - я только заполнил пробелы, вообще не меняя ваш код.

#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;
}

Я получаю этот результат:

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

Обратите внимание, что в конечном итоге в наборе сохраняются все три элемента, и ваш журнал сравнения показывает разумное поведение.

Редактировать:

Ваша ошибка находится в этой строке:

SimulatedDiskFile temp_file(current_request->getFileName(), current_request->getResponseSize());

disk.addFile(&temp_file);

Вы берете адрес локального объекта.Каждый раз в цикле этот объект уничтожается, а следующий объект выделяется точно в том же пространстве.Таким образом, в конце цикла все еще существует только конечный объект, и вы добавили несколько указателей на один и тот же объект.Вне цикла все ставки отменяются, потому что теперь ни один из объектов не существует.

Либо выделите каждому SimulatedDiskFile значение new (как в моем тесте, но тогда вам придется выяснить, когда их удалять), либо вообще не используйте указатели (намного проще, если это соответствует ограничениям вашей проблемы).

Другие советы

И вот проблема:

SimulatedDiskFile temp_file(current_request->getFileName(),
                                   current_request->getResponseSize());
disk.addFile(&temp_file);

Вы добавляете указатель на переменную, которая немедленно уничтожается. Вам необходимо динамически создавать объекты 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 выйдет из области видимости в момент следующей итерации цикла while.Вам нужно изменить код вставки.Создайте объекты SimulatedDiskFile в куче и нажмите в противном случае, если объекты меньше, затем сохраните по значению в set.

Согласитесь с @Earwicker. Все выглядит хорошо. Вы смотрели в all_requests? Может быть, все имена файлов там одинаковые, а все остальное работает нормально? (просто мысли вслух)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top