8

我知道这个链接已经回答了类似的问题帮助我修复这个 C++ std::set 比较器 ,但不幸的是我面临着完全相同的问题,我无法理解它背后的原因,因此需要一些帮助来解决它。

我正在使用 VS2010,我的发布二进制文件运行良好,没有任何问题,但调试二进制文件报告:

在此处输入图像描述

我的比较器看起来像这样:

struct PathComp {
    bool operator() (const wchar_t* path1, const wchar_t* path2) const
    {
        int c = wcscmp(path1, path2);
        if (c < 0 || c > 0) {
            return true;
        }
        return false;
    }
};

我的集合是这样声明的:

set<wchar_t*,PathComp> pathSet;

有人可以建议我为什么我的调试二进制文件在这个断言上失败了吗?是因为我使用 wcscmp() 函数来比较存储在我的集合中的宽字符串吗?

提前致谢!!!

4

3 回答 3

18

std::set需要一个行为类似于operator<or的有效比较器std::less

std::set 代码检测到您的 operator< 无效,并作为对您的帮助触发了您显示的断言。

确实:你的 Comperator 看起来像一个operator!=,而不像一个operator<

operator<应该遵循的规则之一是,a<b并且b<a不能同时为真。在您的实施中,它是。

将您的代码更正为:

bool operator() (const wchar_t* path1, const wchar_t* path2) const
{  
  int c = wcscmp(path1, path2);
  return (c < 0);
}

你应该没事。

于 2011-05-04T16:25:48.727 回答
9

问题是您的比较器不会引起严格的弱排序。它应该只对“更少”的路径真正返回 true - 而不是所有不同的路径。将其更改为:

struct PathComp {
    bool operator() (const wchar_t* path1, const wchar_t* path2) const
    {
        int c = wcscmp(path1, path2);
        if (c < 0) {  // <- this is different
            return true;
        }
        return false;
    }
};

或者,仅使用c > 0也可以 - 但该集合将具有相反的顺序。

该算法需要知道更小和更大之间的差异才能工作,只是不等并不能提供足够的信息。如果没有小于/大于信息,集合就不可能维持顺序——但这就是集合的全部意义所在。

于 2011-05-04T16:25:37.823 回答
1

在花了更多时间之后,我们最终决定采用另一种对我有用的方法。

所以我们使用这种方法将 wchar_t* 转换为字符串:

// Converts LPWSTR to string
bool convertLPWSTRToString(string& str, const LPWSTR wStr)
{
    bool b = false;
    char* p = 0;
    int bSize;    
    // get the required buffer size in bytes
    bSize = WideCharToMultiByte(CP_UTF8,
        0,
        wStr,-1,
        0,0,
        NULL,NULL);     
    if (bSize > 0) {
        p = new char[bSize];
        int rc = WideCharToMultiByte(CP_UTF8,
            0,
            wStr,-1,
            p,bSize,
            NULL,NULL);
        if (rc != 0) {
            p[bSize-1] = '\0';
            str = p;
            b = true;
        }
    }
    delete [] p;
    return b;
}

然后将该字符串存储在集合中,通过这样做,我不必担心比较存储的元素以确保所有条目都是唯一的。

// set that will hold unique path
set<string> strSet;

所以我所要做的就是:

string str;
convertLPWSTRToString(str, FileName);
// store path in the set
strSet.insert(str);

虽然我仍然不知道是什么导致我使用时出现“调试断言失败”问题a set comparator (PathComp) for set<wchar_t*,PathComp> pathSet;

于 2011-05-04T10:04:34.240 回答