【问题标题】:Strange behaviour of std::find, returns true when the element is not in the vectorstd::find 的奇怪行为,当元素不在向量中时返回 true
【发布时间】:2019-04-11 19:25:09
【问题描述】:

看起来很直接的例子,典型的 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_;
}

当我创建一个局部向量时,即

auto tmp = generic->vec(),

代码有效。

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

【问题讨论】:

  • auto tmp = generic-&gt;vec(); 是一个很好的解决方案

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


【解决方案1】:

问题在于您的vec 函数返回向量按值。这意味着对vec 的每次调用都将返回一个不同的不同的 向量对象。并且来自不同向量的迭代器不能相互比较。

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

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

【讨论】:

    【解决方案2】:

    std::vector&lt;uint64_t&gt; 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 循环时,这些事情可能很难发现,例如

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

    这不是问题,但在底层,这个 sn-p 被扩展,使得vec() 的返回值绑定到一个auto&amp;&amp; 变量,并且任何对*begin/*end 方法的调用都指向同一个对象。

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

    【讨论】:

    • 实际上,您已经通过将来自不同向量的迭代器相互比较来调用未定义的行为...
    • @Aconcagua 好提示,我不知道它是 UB!我会编辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-11
    • 2014-02-02
    • 2013-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多