如何在通过引用传递的 std::vector 上使用 std::search?

How to use std::search on a std::vector passed by reference?

如果我在 C++ 中有一个通过引用获取 std::vector<unsigned char> 的函数,我如何使用 std::search 来查找签名?

代码如下所示:

int check (const std::vector<unsigned char>& vect)
{
  std::string signature("<!-- signature -->");
  std::string signature2("<!-- another -->");
  std::vector<unsigned char>::iterator itr;
  unsigned int kind = 0;

  itr = std::search(vect.begin(),vect.end(),signature.begin(),signature.end());
  if (itr!=vect.end()) kind=1;
  if (kind == 0) 
  {
    itr = std::search(vect.begin(),vect.end(),signature2.begin(),signature2.end());
    if (itr!=vect.end()) kind=2;
  }
  return kind;
}

vect 很大,所以复制它是可行的,但这是一个糟糕的解决方案。

为什么不能编译?

适用于 gcc-5.1,example here:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

bool check (const std::vector<unsigned char>& vect)
{
  std::string signature("<!-- signature -->");
  auto itr = std::search(vect.begin(),vect.end(),signature.begin(),signature.end());
  if (itr!=vect.end()) /* do something */
    return false;
}

int main() {
    check(std::vector<unsigned char>{'a', 'b', 'c'});
    return 0;
}

编辑: 下面是错误的。问题是问题中的代码实际上并没有显示问题。 TartanLlama 有正确的解决方案。

Edit2: 唉: 写这篇文章的时候我心情不好。 charunsigned char 之间的差异会导致问题 - 它们是不同的类型。然而,对 "char defaults to signed on Windows" 的引用具有误导性;它 true char 是否签名是实现定义的(并且在 Windows 上它默认为签名),但无论它是签名还是未签名, 它仍然是不同于 unsigned charsigned char.

的类型

您的问题是 std::string::begin returns 一个指向 char 的迭代器,而您的向量包含 unsigned char。我怀疑您在 windows 上,其中 char 默认为已签名。

解决方法是重新解释转换(在这种情况下是安全的):

const auto sigstart = reinterpret_cast<const unsigned char*>(&signature.front());
const auto itr = std::search(vect.begin(), vect.end(),
                             sigstart, sigstart+signature.len());

问题是您正在迭代 const std::vector<unsigned char>,但您尝试将迭代器从它分配给非常量 std::vector<unsigned char>::iterator

一个简单的解决方法是为 itr 声明正确的类型:

std::vector<unsigned char>::const_iterator itr;

如果您使用的是 C++11,我会改用 auto

auto itr = std::search(vect.begin(),vect.end(),signature.begin(),signature.end());