尝试 find_if 向量中的 unique_ptr 时出现编译错误

Compilation error when trying to find_if an unique_ptr in a vector

此代码:

#include <memory>
#include <vector>
#include <algorithm>

struct Foo
{
    int bar;

    Foo(const int val) :
        bar(val)
    {
    }
};

int main() {
    std::vector<std::unique_ptr<Foo>> vec;
    vec.emplace_back(std::make_unique<Foo>(42));
    Foo* ptr = vec.back().get();
    auto& it = std::find_if(vec.begin(), vec.end(), [&](std::unique_ptr<Foo>& p)
    {
        return p.get() == ptr;
    });
    if (it != vec.end())
    {
        vec.erase(it);
    }

    return 0;
}

在 MSVC 中工作正常,但在 GCC 5.1 中出错:

prog.cpp: In function 'int main()':

prog.cpp:19:25: error: invalid initialization of non-const reference of type '__gnu_cxx::__normal_iterator*, std::vector > >&' from an rvalue of type '__gnu_cxx::__normal_iterator*, std::vector > >' auto& it = std::find_if(vec.begin(), vec.end(), [&](std::unique_ptr& p)

  1. 哪个编译器有问题?
  2. 如何从 std::unique_ptrstd::vector 中正确删除指针?

gcc 在这里是正确的。您不能用右值初始化左值引用,而您这样做是为了 it 对迭代器的引用(std::find_if returns 一个右值)

auto& it = std::find_if(vec.begin(), vec.end(), [&](std::unique_ptr<Foo>& p)
    ^

要么把它变成一个对象:

auto it = std::find_if(vec.begin(), vec.end(), [&](std::unique_ptr<Foo>& p)

demo

或常量引用:

auto const& it = std::find_if(vec.begin(), vec.end(), [&](std::unique_ptr<Foo>& p)

demo

除此之外,您从向量中删除元素的代码是正确的

如果您打开 4 级警告,VS2015 将发出正在使用非标准扩展的警告 /W4:

warning C4239: nonstandard extension used:
note: A non-const reference may only be bound to an lvalue

#pragma warning( push, 3 )  
#include <memory>
#include <vector>
#include <algorithm>
#pragma warning( pop ) 
#pragma warning( disable : 4710 )

struct Foo
{
    int bar;

    Foo(const int val) :
        bar(val)
    {
    }
};

int main() {
    std::vector<std::unique_ptr<Foo>> vec;
    vec.emplace_back(std::make_unique<Foo>(42));
    Foo* ptr = vec.back().get();
    auto& it = std::find_if(vec.begin(), vec.end(), [&](std::unique_ptr<Foo>& p)
    {
        return p.get() == ptr;
    });
    if(it != vec.end())
    {
        vec.erase(it);
    }

    return 0;
}

生产:

1>c:\users\flatmouse\documents\visual studio 2015\projects\project79\project79\source.cpp(25): warning C4239: nonstandard extension used: 'initializing': conversion from 'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<std::unique_ptr<Foo,std::default_delete<_Ty>>>>>' to 'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<std::unique_ptr<Foo,std::default_delete<_Ty>>>>> &'
1>          with
1>          [
1>              _Ty=Foo
1>          ]
1>  c:\users\flatmouse\documents\visual studio 2015\projects\project79\project79\source.cpp(25): note: A non-const reference may only be bound to an lvalue