在c ++中,使用std :: numeric_limits <double> :: max()作为特殊的“标志”是否安全?</double>

时间:2015-02-16 19:11:01

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

给出

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 )参考comment by the OP。 - Alf

1 个答案:

答案 0 :(得分:3)

让我们来看看你的&#34;基线&#34;代码,你说你想做&#34;等价的&#34;的:

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

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

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

如果按照所需的最小操作次数来考虑,则必须移动a中的许多/大部分/全部元素,以便删除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算法和自定义谓词(仿函数)重新构造它,它可以记住它的当前&#34; ind中的位置,但代码不会少得多,也可能难以理解。