【问题标题】:STL string comparison functorSTL 字符串比较函子
【发布时间】:2009-06-16 12:06:40
【问题描述】:

我有以下仿函数:

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 的比较函子。问题是,它只插入第一个元素。通过将控制台输出添加到比较器函数中,我了解到它实际上每次都将文件名与自身进行比较。

其他相关行是:

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

我希望我能就发生的事情提供我的假设,但我实际上不知道。提前感谢您的任何指点。

【问题讨论】:

  • 如果看起来每次都比较相同的文件名,那么它不会在第一个成员之后插入任何新成员,因为对于集合,每个新文件都比较为既不“小于”也不“不”大于'集合中已有的一个文件。您从哪里获取要传递给 addFile 方法的文件指针?
  • 什么代码在调用 addFile?
  • 编辑问题以添加这些信息。

标签: c++ string stl functor


【解决方案1】:

从功能上讲,您发布的代码没有任何问题。这是一个完整的测试程序——我只是填空,根本没有改变你的代码。

#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 运算符实际上解决了它。在我的天真中,我认为 C++ 垃圾收集器不会删除 SDF 块,因为它有一个指向它的指针(在容器中)。我完全使用指针来适应约束,因为我必须根据它们在集合中出现的顺序来修改对象。但是之后删除它们不会有问题。非常感谢!
  • 你真的需要阅读 C++ 内存管理 - 没有 C++ 垃圾收集器。
  • 提防幼稚的描述,例如在这个网站上。去图书馆看看 Stroustrup、Herb Sutter、Scott Meyers。
  • 同时忽略任何关于 98 年之前写的书。
【解决方案2】:

这就是问题所在:

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

您正在添加一个指向立即销毁的变量的指针。您需要动态创建 SDF 对象。

【讨论】:

    【解决方案3】:
    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 对象,否则如果对象较小,则按值存储在集合中。

    【讨论】:

      【解决方案4】:

      同意@Earwicker。一切看起来都不错。你看过 all_requests 里面了吗?也许那里的所有文件名都相同,其他一切都正常吗? (只是在这里大声思考)

      【讨论】:

        猜你喜欢
        • 2020-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多