unique_ptr & vector,试图访问已删除的函数,Visual Studio 2013

Posted

技术标签:

【中文标题】unique_ptr & vector,试图访问已删除的函数,Visual Studio 2013【英文标题】:unique_ptr & vector, trying to access deleted function, Visual Studio 2013 【发布时间】:2014-03-30 23:18:26 【问题描述】:

我正在尝试使用 unique_ptr 来管理我的内存,而 VS2013 似乎在我认为不应该的时候给我带来了麻烦。

似乎编译器出于某种原因试图访问已删除的复制构造函数,而实际上它确实没有理由这样做。

这是我的一门课的样子:

class Mesh

public:
    Mesh(oglplus::Program* program, const std::vector<Vertex>& vertices, 
                    const std::vector<GLuint>& indices);
    void draw();
private:
    const oglplus::Program* _program;
    std::vector<Vertex> _vertices;
    std::vector<GLuint> _indices;
    oglplus::Buffer _faceBuffer;
    oglplus::Buffer _vertexBuffer;
    oglplus::VertexArray _vao;
;

class Model

public:
    Model(std::string filename, oglplus::Program* program);
    void draw();
private:
    const oglplus::Program* _program;
    std::vector<std::unique_ptr<Mesh>> _meshes;
;

问题在于线路

 std::vector<std::unique_ptr<Mesh>> _meshes;

它开始喷出类似的东西

2>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(593): error C2280: 'std::unique_ptr<Model::Mesh,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function
2>          with
2>          [
2>              _Ty=Model::Mesh
2>          ]
2>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1486) : see declaration of 'std::unique_ptr<Model::Mesh,std::default_delete<_Ty>>::unique_ptr'
2>          with
2>          [
2>              _Ty=Model::Mesh
2>          ]
2>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(592) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
2>          with
2>          [
2>              _Ty=std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>
2>          ]
2>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(723) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled
2>          with
2>          [
2>              _Ty=std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>
2>          ]
2>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits(572) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
2>          with
2>          [
2>              _Ty=std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>
2>          ]
2>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(650) : see reference to class template instantiation 'std::is_empty<_Alloc>' being compiled
2>          with
2>          [
2>              _Alloc=std::allocator<std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>>
2>          ]
2>          c:\users\vitali\projects\3d-stg\source\model\model.hpp(45) : see reference to class template instantiation 'std::vector<std::unique_ptr<Model::Mesh,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' being compiled
2>          with
2>          [
2>              _Ty=Model::Mesh
2>          ]
2>  model.cpp

我没有使用std::vector::resize() 或类似的东西(事实上我注释掉了我的 _meshes 向量的所有用途,甚至尝试完全注释掉实现无济于事),所以我不明白为什么编译器给我带来了问题。

有人有什么想法吗?


感谢 Preetish Kakkar 发现问题。事实证明,编译器使用 Mesh 类的复制构造函数和 operator= 隐式生成函数是一个问题,迫使编译器尝试使用已删除的函数。

【问题讨论】:

尝试为Mesh 实现移动构造函数。 AFAIK,VS2013 不会自动生成移动构造函数/移动赋值运算符。 是的,但我的理解是 std::vector 不使用移动构造函数,因此不应该出现错误。如果我正确读取错误,则它与复制构造函数有关。如果不是 std::vector<:unique_ptr>> _meshes;我做 std::unique_ptr _mesh,一切都编译得很好。另外,如果我只使用常规指针 std::vector _meshes,一切都编译得很好。 -std=c++11 不适用于 VS afaik 这是 VS 2013 中的一个已知 bug。它被 Microsoft 归类为活动 bug。见下文:connect.microsoft.com/VisualStudio/feedback/details/858243/… 该错误仅适用于 C++/CLI。 【参考方案1】:

我重现了你的问题,下面是示例代码。

#include <vector>
#include <memory>

class Mesh

public: 
    Mesh() 
    void draw() 
private:
;

class Model

public:
    Model() 
    void draw() 
private:
    typedef std::unique_ptr<Mesh> MeshUniquePtr;
    std::vector<MeshUniquePtr> _meshes;
;


int _tmain(int argc, _TCHAR* argv[])

    Model m;
    Model m1;
    m = m1; // causes error as you can't copy unique ptr

    return 0;

问题是在某些时候您试图复制两个无法完成的模型对象,因为 unique_ptr 是不可复制的。

【讨论】:

你能粘贴编译时出错的文件代码吗?仅当您尝试复制 unique_ptr 时才会发生此错误(至少从您发布的内容来看是这样)。我确信它正在发生。 所以我在你的代码中发现了问题,Ship.hpp 就是问题所在。它使用 Model::model 很好,但由于它试图复制而导致问题。在 Model.hpp 中将复制构造函数和赋值运算符设为私有将修复它。添加模型(模型常量&); void operator=(Model const&);在模型类私有部分中 或者您可以通过从 Ship(const Ship&) = default; 中删除默认值来修复它。如果您不想让船舶可复制,那么只需将赋值和复制构造函数设为私有 - 不要为它们提供默认实现,因为默认会尝试在内部复制导致错误。 我有其他建议不包括 typedefs.hpp 中的所有内容 - 包括每个 cpp 中需要的任何内容 为什么你认为在 typedefs.hpp 中包含所有内容是不好的?当然它会减慢编译时间,但如果将来我决定使用预编译头文件,这很容易。包含我需要的所有内容的问题是,很难跟踪我真正需要的内容,并且我最终有很多“无用”的标头弄脏了我的代码。

以上是关于unique_ptr & vector,试图访问已删除的函数,Visual Studio 2013的主要内容,如果未能解决你的问题,请参考以下文章

我怎样才能让这个涉及unique_ptr的代码编译?

如何将其切换到 unique_ptr?

矢量的独特副本

如何在 std 算法中使用 unique_ptr 的 transform_iterator

vector系列--vector<unique_ptr<;;初始化(所有权转移)

用 unique_pointers 填充向量