質問
次のファンクターがあります。
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;
}
}
};
これは厳密に弱い順序付けであると想定されており、デバッグ目的でこの長さ (1 行のみの可能性があります) になっています。
このファンクターを stl::set のコンパレーターファンクターとして使用しています。問題は、最初の要素のみが挿入されることです。コンパレーター関数にコンソール出力を追加することで、実際にはファイル名とそれ自体を比較していることがわかりました。 毎回.
その他の関連する行は次のとおりです。
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 はリストであり、クラス 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
最終的にセットには 3 つすべてが保存され、比較ログには賢明な動作が示されることに注意してください。
編集:
あなたのバグは次の行にあります。
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オブジェクトを作成し、オブジェクトが小さい場合はプッシュして値にセットで保存します。
@Earwickerに同意します。すべてがよさそうだ。 all_requestsをご覧になりましたか?おそらくすべてのファイル名が同じで、他のすべてが正常に機能していますか? (ここで大声で考えてください)