c++ - 如何将 std::vector 插入具有自定义排序功能的 std::set
问题描述
注意这里的问题已经解决了,和插入无关,而是一个未初始化的结构体成员变量!希望这个问题及其答案可以帮助另一个菜鸟避免这样的错误。
我想将文件名的 std::vector 插入到具有客户排序器结构的 std::set 中,用于按日期而不是按字母顺序对文件进行排序。
使用默认的字母顺序,我可以简单地将一个向量插入到我的集合中:
std::set<std::string> mySet;
std::vector<std::string> myVector;
myVector.push_back("Banana.txt");
myVector.push_back("Apple.txt");
myVector.push_back("Cat.txt");
mySet.insert(myVector.begin(), myVector.end());
这将完全符合我的期望:按字母顺序排列的文件名 std::set。
现在,如果我有一个按日期而不是文件名排序的自定义排序器,如下所示:
struct DateOrderSorter
{
bool operator()(const std::string& file1, const std::string& file2)
{
struct stat buf_stat1;
struct stat buf_stat2;
std::string fullpath1 = path + file1;
std::string fullpath2 = path + file2;
stat(&fullpath1[0], &buf_stat1);
stat(&fullpath2[0], &buf_stat2);
return buf_stat1.st_ctime < buf_stat2.st_ctime;
}
std::string path;
};
我将我的设置声明为:
std::set<std::string, DateOrderSorter>
然后声明一个 DateOrderSorter 的实例:
DateOrderSorter dateOrderSorter;
dateOrderSorter.path = "C:/random_path_that_has_been_verified_to_work"
当我做同样的插入时:
mySet.insert(myVector.begin(), myVector.end());
它只返回按日期排序的第一个和最后一个文件。所以只有 myVector.begin() 和 myVector.end()。
- 首先,为什么会有这种行为?
- 我该怎么做才能将向量插入通过我的客户分类器订购的集合中。
我试过了
std::vector<std::string>::iterator vector_it = myVector.begin();
std::vector<std::string>::iterator vector_end = myVector.end();
for (; vector_it!= vector_end; ++vector_it) {
mySet.insert(*vector_it);
}
但这并没有完全复制向量,而且顺序很奇怪。它没有遵循名称或日期顺序..
解决方案
path
比较函数的成员默认初始化为“”,因此stat
会出现错误(由于未在代码中检查返回值,因此错误不会被注意到),并且buf_stat1.st_ctime < buf_stat2.st_ctime
正在比较未初始化的内存。
这意味着比较函数可以为两者返回 true a < b
:a > b
这违反了严格的弱排序规则,因此您会观察到这种奇怪的行为。
要解决此问题,您可以创建path
一个静态成员,并验证它stat
不会出错,如下所示:
struct DateOrderSorter
{
bool operator()(const std::string& file1, const std::string& file2)
{
struct stat buf_stat1;
struct stat buf_stat2;
std::string fullpath1 = path + file1;
std::string fullpath2 = path + file2;
int r = stat(&fullpath1[0], &buf_stat1);
assert(r==0);
r = stat(&fullpath2[0], &buf_stat2);
assert(r==0);
return buf_stat1.st_ctime < buf_stat2.st_ctime;
}
static std::string path;
};
并像这样初始化它:
DateOrderSorter::path = "...";
推荐阅读
- rest - spring boot rest api 单访问
- angular - 错误:找不到模块“angularfire2/database-deprecated”appmodule ionic 3, Angularfire2
- spring - 无法与 SpringBoot 和 RestTemplate 进行服务到服务通信
- c# - 我是否应该始终将 CancellationToken 添加到我的控制器操作中?
- c# - 查询字符串的属性路由
- python - 如何在 conftest.py 中访问 json 文件(像 config.json 这样的测试数据)
- javascript - JS:将所有 img src 相对 url 替换为绝对
- ms-access - 如果在访问 VBA 中选中复选框,则隐藏/取消隐藏按钮
- javascript - Vue.JS - 主要布局组件和路由
- powershell - 如何使用 DSC 在 Azure VM 上安装存储在 Azure 文件共享中的 exe 文件?