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

In c++, is it safe to use std::numeric_limits<double>::max() as a special "flag"?

给定

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

其中 ind 1 升序排列。

我想执行以下操作:

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 中的双打是安全的,并且在工作应用程序中这个向量的实践中永远不会出现限制,所以应该没问题吧?

对此有什么想法吗?


1) 参考 。 – 阿尔夫

让我们看看你的 "baseline" 代码,你说你想做 "equivalent" 的:

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

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

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

如果按照所需的最少操作数考虑,则必须移动 a 中的 many/most/all 个元素才能擦除 ind 中的元素].您不想 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 中的 "current" 位置,但代码不会少很多,而且可能是更难理解。