【问题标题】:Is there a safe alternative to std::equal?是否有 std::equal 的安全替代方案?
【发布时间】:2013-04-25 21:47:17
【问题描述】:

std::equal() 是不安全的,因为函数无法知道它是否会超出要比较的第二个容器的长度。那就是:

std::vector< int > v( 100 );
std::vector< int > w( 10 );
bool same = std::equal( v.begin(), v.end(), w.begin() );

...将导致w 的缓冲区溢出。

我们当然可以测试这些东西 (v.size() == w.size()),但是像 Visual Studio 2010 这样的编译器仍然报告函数本身是不安全的。事实上,它在某种基本意义上是不安全的:经验水平各异的程序员团队最终会忘记比较大小。

一个安全的替代方案很容易实施。

template< typename Iter1, typename Iter2 >
bool equal_safe( Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2 )
{
    while( begin1 != end1 && begin2 != end2 )
    {
        if( *begin1 != *begin2 )
        {
            return false;
        }
        ++begin1;
        ++begin2;
    }
    return begin1 == end1 && begin2 == end2;
}

但是标准库中是否有安全的替代方案?

【问题讨论】:

  • 安全的替代方法到底是什么?只比较两个std::vectors?还是两个迭代器范围?
  • @sftrabbit 做 std::equal() 所做的事情。比较两个迭代器范围。
  • 如果 == 不满足您的要求,编写一个 safe_equal 实现很容易。
  • 我不确定我是否同意这个评估,尽管我理解投诉:std::equal 基本上是一种在 迭代器范围 上工作的算法,就其本质而言,就像 all 范围内的其他 C++ 算法一样,算法不会检查这些范围。这一点在标准库中有压倒性的一致性,所以我认为很难出错。您将获得一个行为完全符合预期的统一界面。

标签: c++ stl containers stl-algorithm


【解决方案1】:

您还可以使用std::lexicographical_compare 两次来确定一个序列是否小于另一个。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,并通过在相等之前检查向量的大小来解决它。

      std::vector< int > v( 100 );
      std::vector< int > w( 10 );
      bool same = (v.size() == w.size()) && std::equal( v.begin(), v.end(), w.begin() );
    

    【讨论】:

      【解决方案3】:

      在 C++14 中,标准库将包含一个带有两对迭代器的 std::equal 版本,类似于您的 safe_equalstd::mismatchstd::is_permutation 相同。

      【讨论】:

        【解决方案4】:

        我自己也想要这样的功能。我在标准库中找不到任何设施。

        如果你愿意使用 boost。 Boost.Range 具有相同的值,我认为这就是您正在寻找的http://www.boost.org/doc/libs/1_53_0/libs/range/doc/html/range/reference/algorithms/non_mutating/equal.html

        【讨论】:

        • Boost 1.54(7月初发布)包含equalis_permutationmismatch的四个迭代器版本。您今天可以从 boost 后备箱中获取代码。
        【解决方案5】:

        vector 有一个 operator== 首先检查大小。在您的示例中,只需使用条件v==w

        【讨论】:

        • 这意味着根据 OP 对安全的定义它是安全的。
        • 好吧,我认为这很清楚,但对于 op 的示例,“v==w”是安全的。
        • @huskerchad 我以向量为例,因为它可以快速创建两个不同大小的向量。但想象一下,这是一个列表......
        • @OldPeculier,我相信所有的 STL 容器都有一个 operator== 以这种方式工作。如果您的问题是您是否可以对任意迭代器执行此操作,答案是否定的,因为仅基于序列中的单个迭代器无法知道序列的长度。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多