2016-12-07 74 views
0

在過去的一兩年中使用C#之後,我的C++變得有點生疏了。返回實例會導致'嘗試引用已刪除的函數'錯誤

我正在寫一個數據庫類,並有一個問題用下面的方法:

CRecordset CAccessDatabaseReader::ExecuteSqlQuery(LPCTSTR pszSqlQuery) 
{ 
    CRecordset recordSet(&m_Database); 
    recordSet.Open(CRecordset::forwardOnly, pszSqlQuery); 
    return CRecordset(recordSet); 
} 

編譯器就行了抱怨與return聲明:

錯誤C2280「的CRecordset :: CRecordset(const CRecordset &)':嘗試引用已刪除的函數

有人可以幫助我明白到底發生了什麼?

+1

的CRecordset似乎是一個不可複製的類。它沒有複製構造函數。 –

+1

在C++中,您可以關閉類的複製,這就是CRecordset所做的。這就是爲什麼你不能按價值回報它。 – PaulMcKenzie

+0

要「返回」這樣的基於CObject的類,您可能必須使用動態分配。 –

回答

1

CRecordset的拷貝構造函數被明確標記爲deleted防止複製CRecordset對象從一個到另一個。

因此,該功能將通過指針返回一個新的對象,需要調用者delete對象時,使用完畢後:

CRecordset* CAccessDatabaseReader::ExecuteSqlQuery(LPCTSTR pszSqlQuery) 
{ 
    CRecordset *recordSet = new CRecordset(&m_Database); 
    if (!recordSet->Open(CRecordset::forwardOnly, pszSqlQuery)) 
    { 
     delete recordSet; 
     return NULL; // or raise an exception 
    } 
    return recordSet; 
} 

CRecordset *rs = reader.ExecuteSqlQuery(TEXT("...")); 
if (rs) 
{ 
    ... 
    delete rs; 
} 

或者更好:

std::unique_ptr<CRecordset> CAccessDatabaseReader::ExecuteSqlQuery(LPCTSTR pszSqlQuery) 
{ 
    std::unique_ptr<CRecordset> recordSet(new CRecordset(&m_Database)); 
    if (!recordSet->Open(CRecordset::forwardOnly, pszSqlQuery)) 
     recordSet.reset(); // or raise an exception 
    return recordSet; 
} 

std::unique_ptr<CRecordset> rs = reader.ExecuteSqlQuery(TEXT("...")); 
if (rs) 
{ 
    ... 
} 
+0

我可以問一下,返回'std :: unique_ptr <>'是什麼意思?爲什麼不只是返回一個常規指針,然後讓調用者將該指針賦值給一個類型爲「std :: unique_ptr <>'的變量?不知何故,這不是那麼簡單嗎? –

+0

如果調用者沒有將原始指針分配給智能指針類?然後,如果調用者忘記「刪除」指針,或者在調用「delete」之前發生未捕獲的異常,則調用者冒着內存泄漏的風險。該函數無法知道調用者是或將不會使用的。所以最好明確一下內存管理的預期。使用智能指針的重點在於避免這些問題。這也有助於函數本身自動管理內存,以防在返回被調用之前出現錯誤。 –

1

CRecordset已經刪除了它的拷貝構造函數,所以你不能按值返回它。您可以改爲返回std::unique_ptr<CRecordset>或參考ExecuteSqlQuery

在刪除拷貝構造函數:https://stackoverflow.com/a/6077164/2449857

在返回引用的函數:Is the practice of returning a C++ reference variable, evil?

+0

這裏沒有「返回參考」 –

+0

@ M.M他說他正在編寫'CAccessDatabaseReader'類。所以他可以讓'ExecuteSqlQuery'返回一個'CRecordset&'或'const CRecordset''如果他做得對。 –

+1

這將是一個壞主意。該線程的答案中的'unique_ptr'示例可能會很有用。 –

相關問題