2012-11-14 38 views
3

我必須爲一個工作構建一個小型的OpenGL包裝器。我試圖避免編寫複製構造函數併爲所有類複製分配。移動一個std :: shared_ptr會導致程序崩潰

一個方法是非常懶惰,從不寫複製是使用指針,但由於指針是邪惡的,我試圖專用std::shared_ptr

問題是通過使用一個構造函數來接收std::shared_ptr值我的程序崩潰,並且當使用完美的轉發它只適用於當我傳遞一個左值。

// 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; 

(...) 

我曾嘗試2種不同的構造函數:

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)) 
{ 
} 

,另一個

Program(std::shared_ptr<Dep> dep1, std::shared_ptr<Dep> 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的右值不起作用。 std :: move上的左值或右值不工作。它只是在調用std :: shared_ptr構造函數時掛起程序(在Program構造函數內)。

我看了斯科特邁耶斯的普遍引用談話,我以爲我理解這一點,這發生在我身上。

回答

1

我看不出什麼毛病此代碼,並測試了OK的http://ideone.com/jlShgB太:

#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); 
} 

當然,如果你改變#if 1#if 0,斷言將引發異常,因爲dep1/dep2不會被移出。

這使我懷疑另一個問題。如果您能夠隔離出現問題的SSCCE,請告訴我。

+0

非常感謝您的回答。該代碼就像我一樣,實際上我只是在我的編譯器vs2012上試過了,效果很好!也許與Dep課程有關?也許它的構造函數? Dep類是一個在其構造函數中執行大量初始化工作的類(但它從不初始化內存或shared_ptr),因爲它的類必須知道它在初始化時會起什麼作用。但我在單獨測試之前做得很好。程序類只是2個Deps的小容器,所以不能這樣做。生病嘗試隔離問題,然後再次詢問這裏尋求幫助。再次感謝。 – sap

+0

好吧,我想出了問題,在Program類中,我正在訪問移動後的參數成員之一,而不是使用類「this->」(我真的不喜歡使用this->但現在我會!)。再次感謝您的幫助,接受您的答案,因爲它對我來說是一個很好的將來參考,用於構建接受std :: shared_ptr的構造函數。再次非常感謝。 – sap

+0

@sap感謝您的反饋。我希望「可能會有所幫助」的想法。另外,我通常會讓成員名稱唯一,比如'_dep1(dep1)'或'_dep1(arg1)'。 – sehe