C++ 移动std::shared_ptr会使程序崩溃

C++ 移动std::shared_ptr会使程序崩溃,c++,shared-ptr,C++,Shared Ptr,我必须为一项工作构建一个小型OpenGL包装器。我试图避免为我所有的类编写复制构造函数和复制赋值 真正懒惰且从不写拷贝的一种方法是使用指针,但由于指针是邪恶的,我正试图专门使用std::shared\u ptr 问题是使用一个构造函数接收一个std::shared_ptrby值,我的程序崩溃了,当使用完美转发时,它只在传递左值时才起作用 // this class doesn't have any default, copy constructors. class Dep { Dep(s

我必须为一项工作构建一个小型OpenGL包装器。我试图避免为我所有的类编写复制构造函数和复制赋值

真正懒惰且从不写拷贝的一种方法是使用指针,但由于指针是邪恶的,我正试图专门使用
std::shared\u ptr

问题是使用一个构造函数接收一个
std::shared_ptr
by值,我的程序崩溃了,当使用完美转发时,它只在传递左值时才起作用

// this class doesn't have any default, copy constructors.
class Dep
{
    Dep(std::string path, GLenum type);
};

class Program
{
std::shared_ptr<Dep> dep1;
std::shared_ptr<Dep> dep2;

(...)
//此类没有任何默认的复制构造函数。
班级副主任
{
Dep(标准:字符串路径,格伦类型);
};
班级计划
{
std::共享ptr dep1;
std::共享的ptr dep2;
(...)
我尝试过两种不同的构造函数:

template <class T, class = typename std::enable_if<std::is_constructible<std::shared_ptr<Dep>, T>::value>::type>
Program(T&& dep1, T&& dep2)
: dep1(std::forward<T>(dep1)), dep2(std::forward<T>(dep2))
{
}
模板
程序(T&&dep1、T&&dep2)
:dep1(std::forward(dep1)),dep2(std::forward(dep2))
{
}
另一个呢

Program(std::shared_ptr<Dep> dep1, std::shared_ptr<Dep> dep2)
: dep1(std::move(dep1)), dep2(std::move(dep2))
{
}
程序(std::shared_ptr dep1,std::shared_ptr dep2)
:dep1(std::move(dep1)),dep2(std::move(dep2))
{
}
我想做的是能够传递左值或右值共享指针,但它不起作用,除非我在前向指针上使用左值,否则每次都会崩溃

// passing these work on the std::forward one, but that's the only case it works
// if i try to use std::make_shared as parameter (for rvalue) it crashes on both
// the std::move and std::forward ones.
auto vs = std::make_shared<GLShader>("TriangleVS.glsl", GL_VERTEX_SHADER);
auto fs = std::make_shared<GLShader>("TriangleFS.glsl", GL_FRAGMENT_SHADER);
//将这些工作传递给std::forward one,但这是它唯一有效的情况
//如果我尝试使用std::make_shared作为参数(对于右值),它会在两个节点上崩溃
//std::move和std::forward。
auto vs=std::make_shared(“TriangleVS.glsl”,GL_顶点着色器);
auto fs=std::make_shared(“TriangleFS.glsl”,GL_FRAGMENT_着色器);
概要:std::forward one上的左值有效。std::forward上的右值无效。std::move one上的左值或右值无效。在调用std::shared_ptr构造函数(在程序构造函数内部)时,它只是挂起程序


我看了Scott Mayer universal references的演讲,我想我已经理解了这一点,这发生在我身上。

我看不出这段代码有任何错误,它在上也测试正常:

#include <memory>
#include <utility>
#include <string>
#include <cassert>

enum GLenum { foo };

// this class doesn't have any default, copy constructors.
struct Dep
{
    Dep(std::string path, GLenum type) {}
    Dep() = delete;
    Dep(Dep const&) = delete;
};

struct Program
{
    std::shared_ptr<Dep> dep1;
    std::shared_ptr<Dep> dep2;

#if 1
    template <class T, class = typename std::enable_if<std::is_constructible<std::shared_ptr<Dep>, T>::value>::type>
    Program(T&& dep1, T&& dep2)
        : dep1(std::forward<T>(dep1)), dep2(std::forward<T>(dep2))
    {
    }
#else
    Program(std::shared_ptr<Dep> dep1, std::shared_ptr<Dep> dep2)
        : dep1(std::move(dep1)), dep2(std::move(dep2))
    {
    }
#endif
};

int main()
{
    auto dep1 = std::make_shared<Dep>("dep1", foo);
    auto dep2 = std::make_shared<Dep>("dep2", foo);
    Program p(std::move(dep1), std::move(dep2));

    assert(!dep1 && !dep2);
}
#包括
#包括
#包括
#包括
enum GLenum{foo};
//这个类没有任何默认的复制构造函数。
结构Dep
{
Dep(std::字符串路径,GLenum类型){}
Dep()=删除;
Dep(Dep const&)=删除;
};
结构程序
{
std::共享ptr dep1;
std::共享的ptr dep2;
#如果1
模板
程序(T&&dep1、T&&dep2)
:dep1(std::forward(dep1)),dep2(std::forward(dep2))
{
}
#否则
程序(std::shared_ptr dep1,std::shared_ptr dep2)
:dep1(std::move(dep1)),dep2(std::move(dep2))
{
}
#恩迪夫
};
int main()
{
auto dep1=std::使_共享(“dep1”,foo);
auto dep2=std::make_shared(“dep2”,foo);
程序p(std::move(dep1),std::move(dep2));
断言(!dep1&&!dep2);
}
当然,如果将
#if 1
更改为
#if 0
,则断言将引发异常,因为dep1/dep2将不会从中移动


这让我怀疑其他地方还有另一个问题。如果你能找出一个出现问题的SSCCE,请告诉我。

非常感谢你的回答。该代码和我的代码一样,事实上我刚刚在我的编译器vs2012上试用过,效果很好!可能与Dep类有关?可能与它的构造函数有关?Dep类是一个在其构造函数中执行大量初始化工作(但它从不初始化内存或共享的\u ptr)因为它是一个必须知道在初始化时它将如何工作的类。但我以前单独测试过它,效果很好。Program class只是一个2个DEP的小容器,所以不能这样。我会尝试隔离问题,然后在这里再次请求帮助。再次感谢。好的,我在我访问的Program类中解决了问题移动后的参数成员,而不是使用带有“this->”的类成员(我真的不喜欢使用this->,但现在我会!)。再次感谢您的帮助,接受您的回答,因为这对我来说是一个很好的未来参考,用于构建接受std::shared\u ptr的构造函数。再次非常感谢。@sap感谢您的反馈。我希望
'assert'
-ing的想法可能会有所帮助。此外,我通常会强调使成员名称唯一,如
\u dep1(dep1)
\u dep1(arg1)