c++ - 在 C++ 中,将 std::numeric_limits<double>::max() 用作特殊的 "flag"是否安全?

标签 c++ remove-if numeric-limits erase-remove-idiom

给定

std::vector<double> a;
std::vector<int> ind;

其中 ind1升序排列的。

我想做以下等同​​的事情:

for (auto it=ind.rbegin();it!=ind.rend();it++) a.erase(a.begin() + *it);

我想到了这个:

for (auto it=ind.begin();it!=ind.end();it++) 
   a[*it] = std::numeric_limits<double>::max();
std::erase(std::remove(a.begin(),a.end(),std::numeric_limits<double>::max()),a.end());

这非常快,但在这种情况下使用 std::numeric_limits::max() 作为标志感觉不对。

当然,感觉不应该在等式中发挥太多作用……清楚地比较 std::remove 中的 double 是安全的,并且在工作应用程序的这个 vector 中实践中永远不会出现限制,所以它应该没事吧?

对此有什么想法吗?


1) 引用 comment by the OP . – 阿尔夫

最佳答案

让我们看看你的“基线”代码,你说你想做以下的“等效”:

std::vector<double> a;
std::vector<int> ind;

for (auto it = ind.rbegin(); it != ind.rend(); it++)
    a.erase(a.begin() + *it);

我们从这里收集到的是 inda 中应该删除的索引 vector ,并且它们按升序排序。这些索引必须从 a 中删除。我假设您的目标是在空间和时间方面高效地做到这一点。

如果您根据所需的最少操作数来考虑它,您必须移动 a 中的许多/大部分/所有元素才能删除 指示的元素找到。您不想 erase() 多次,因为这意味着不止一次移动某些元素。一个最佳解决方案(在一般情况下,不对 a 中的值施加特殊要求)如下所示:

size_t slow = 0; // where we are currently copying "to"
std::vector<int> inditer = ind.begin();
for (size_t fast = 0; fast != a.size(); ++fast) {
    if (inditer != ind.end() && *inditer == fast) {
        // "remove" this element by ignoring it
        ++inditer;
    } else {
        a[slow] = a[fast];
        ++slow;
    }
}
a.resize(slow);

现在,您可能可以使用 STL 算法和一个自定义谓词(仿函数)来重新表述它,它会记住它在 ind 中的“当前”位置,但是代码不会少很多,而且可能会更难理解。

关于c++ - 在 C++ 中,将 std::numeric_limits<double>::max() 用作特殊的 "flag"是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28548637/

相关文章:

c - 为什么 FLT_MIN 等于零?

c++ - 在 C++ 中使用 std::complex<T> 创建复无穷大

c - scanf 成功但存储的值不适合某些大的 float

c++ - 相同的代码,不同的结果?从其他项目中包含有什么问题?

c++ - 深入理解strcat和strlen函数

c++ - 使用 gcc 进行静态和动态链接

c++ - webrtc - GetStats() 使用空 RTCStatsReport 调用 OnStatsDelivered

java - 使用流删除深度元素

c# - 替换/删除与正则表达式 (.NET) 不匹配的字符

c++ - std::remove_if - lambda,不从集合中删除任何内容