2015-07-10 40 views
0

我試圖鏈接一些函數,但在調用第一個函數之後,析構函數被調用;然後在範圍的末尾再次調用析構函數。析構函數在返回*之後調用

int i=0; 
class Winbitmap{ 
    public: 
    int index=i++; 
    Gdiplus::GdiplusStartupInput gdiplusStartupInput; 
    ULONG_PTR gdiplusToken; 
    Gdiplus::Bitmap* bitmap; 
    Winbitmap(); 
    ~Winbitmap(); 
    Winbitmap& getCapture(int,int,int,int); 
}; 
Winbitmap::Winbitmap(){ Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); } 
Winbitmap::~Winbitmap(){ 
    //{delete bitmap;} 
    std::wcout << L"destructed:" << index << std::endl; 
    Gdiplus::GdiplusShutdown(gdiplusToken); 
} 
Winbitmap& Winbitmap::getCapture(int x=0, int y=0, int w=0, int h=0) { 
    bitmap = new Gdiplus::Bitmap(captureWindow(GetDC(GetDesktopWindow()),x,y,w,h),NULL); 
    std::wcout << L"captured:" << index << std::endl; 
    return *this; 
} 

這是我打算如何使用它:

Winbitmap bitmap1 = Winbitmap().getCapture(); 
std::wcout<<L"confirmed1\n"; 
Winbitmap bitmap2 = Winbitmap().getCapture(); 
std::wcout << L"confirmed2\n"; 
//If I try to use any of the bitmaps later, the program hangs 

Output: 

captured:0 
destructed:0 
confirmed1 
captured:1 
destructed:1 
confirmed2 
destructed:1 
destructed:0 

我怎樣才能回到正確的對象的引用,而不調用析構函數?

+1

默認的拷貝構造函數被用來將'getCapture()'返回的臨時拷貝拷貝到'bitmap1'中。你忘了遵守[三項規則](https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming))。 –

+0

我沒有看到「位圖」是一個指針的原因。連續調用兩次getCapture會泄漏內存。 – chris

+0

位圖是不可複製的,所以我必須將它存儲在指針中。 – shuji

回答

1

線:

Winbitmap bitmap1 = Winbitmap().getCapture(); 

創建臨時對象,臨時對象調用getCapture(),調用複製構造構建bitmap1,然後破壞臨時對象。

您可以使用:

Winbitmap const& bitmap1 = Winbitmap().getCapture(); 

然而,

我建議使用:

Winbitmap bitmap1; 
bitmap1.getCapture(); 

這更清晰的閱讀和理解。

0

定義移動構造函數應該解決您的問題,只要你能使用C++ 11(我敢肯定VS2013不支持此):

WinBitmap::WinBitmap(WinBitmap&& bmp) : index(bmp.index), gdiplusToken(bmp.gdiplusToken), bitmap(bmp.bitmap) { 
    bmp.bitmap = NULL; // Because the new WinBitmap has now acquired ownership of the pointer. 
} 

那麼你的析構函數將確保bitmap不爲空在delete之前。

+0

刪除null很好。 – chris

+0

你錯了。刪除null將引發段錯誤。 (即使不這樣,你也不想刪除null - 這可能就是程序代碼開始的位置。) – celticminstrel

+1

請參閱[expr.delete]:*在第一個選項(刪除對象)中, ,刪除的操作數的值可以是空指針值,指向由先前的新表達式創建的非數組對象的指針,或者指向表示這樣的對象的基類的子對象(1.8) 的指針(第10條)。如果沒有,行爲是不確定的。* – chris

相關問題