std :: find的奇怪行为,当元素不在向量中时返回true

时间:2018-11-08 09:48:48

标签: c++ c++11 c++14

看起来很简单,std :: find的典型用法

for ( auto element : generic->vec() )
        LOG << element;

    LOG << channel;

    if ( !gen->vec().empty() ) {

        if(std::find(generic->vec().begin(), generic->vec().end(), channel) != generic->vec().end()){

            LOG << "Found";
            ;// Found the item
        } else {

            LOG << "Not Found";
            return false;

        }
}

请检查日志文件

2018-11-08, 09:37:18 [INFO] - [140455150589696] - 1
2018-11-08, 09:37:18 [INFO] - [140455150589696] - 2
2018-11-08, 09:37:18 [INFO] - [140455150589696] - 4
2018-11-08, 09:37:18 [INFO] - [140455150589696] - 12
2018-11-08, 09:37:18 [INFO] - [140455150589696] - 40
2018-11-08, 09:37:18 [INFO] - [140455150589696] - Found

向量包含1,2,4,12,我们要测试的传入值是否属于向量40。std :: find返回true,表示已找到。

vec()方法返回一个uint64_t元素数组:

std::vector<uint64_t>  vec() const {
  return vec_;
}

当我创建本地矢量时,即

  

自动tmp =通用-> vec(),

代码有效。

我的代码中的错误在哪里?当检查40是否属于[1,2,4,12]时,我希望得到“未找到”。

2 个答案:

答案 0 :(得分:12)

问题是您的vec函数通过值返回向量 。这意味着每次调用vec都会返回一个不同不同矢量对象。而且来自不同向量的迭代器不能相互比较。

简单的解决方案是通过引用返回向量

std::vector<uint64_t> const&  vec() const { ... }

答案 1 :(得分:3)

std::vector<uint64_t> vec() const的签名表示返回右值(vec_的副本)。只要您不比较对来自不同调用的vec()元素的引用,就可以了。示例:

auto v1 = vec();
auto v2 = vec();

v1.begin() != v2.begin(); // Don't do that - UB

这与

相同
vec().begin() != vec().begin(); // Again, UB

感谢@Aconcagua指出比较首先是未定义的行为,另请参见this question

例如,当您习惯于基于范围进行循环时,这些事情可能很难发现。

for (const auto& value : vec()) { /* ... */ }

这不是问题,但是在后台,此代码段被扩展为将vec()的返回值绑定到auto&&变量,并且对*begin/*end方法的任何调用都引用相同的对象。

长话短说:在请求迭代器之前将返回值绑定到变量,或更改签名ov vec()使其返回引用而不是副本。