2016-12-07 13 views
0

過去10年または2年間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年代には、コンストラクタを明示的に一方から他方へCRecordsetオブジェクトのコピーを防ぐためにdeletedとしてマークされているコピーします。

ので、関数がポインタによって新しいオブジェクトを返し、それを使用して終了したときにオブジェクトを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'を呼び出す前にキャッチされていない例外が発生した場合にメモリリークを引き起こします。この関数は、呼び出し元が何を使用するのか、使用しないのかを知る方法がありません。だから、どのようなメモリ管理が期待されているかを明示するのが良いでしょう。スマートポインタを使用することの全ポイントは、この種の問題を避けることです。これはまた、 'return'が呼び出される前に何らかの問題が発生した場合に、関数自身がメモリを自動管理するのに役立ちます。 –

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'が正しいとすれば、' ExecuteSqlQuery'は 'CRecordset&'または 'const CRecordset&'を返します。 –

+1

それは悪い考えです。そのスレッド上の答えの中の 'unique_ptr'の例は役に立ちます。 –

関連する問題