『Effective C艹』読書ノート(14)
1167 ワード
条項21:オブジェクトを返さなければならない場合、referenceに戻ることを妄想しないでください.
いずれの場合も、参照を伝達することで値を返すことはできません.次のコードを見てください
実際には、この関数の戻り値に対する読み書き操作は、返されるオブジェクトが関数スタック内のオブジェクトであるため、関数が終了するとオブジェクトが破棄されるため、エラーを返します.破棄されたオブジェクトを使用するとエラーが発生します.
次に、スタックに割り当てる
今度の呼び出し関数は正確に演算結果を返すことができるようになった.しかし、これは依然として問題のあるコードです.今回の問題はメモリ漏れです.*演算子を呼び出した後に発生したオブジェクトを削除する保証はありません.毎回演算結果オブジェクトをdeleteに落とすことに注意していますが、a=b*c*dを行います.この演算ではnew操作が2回行われ、その隠れたオブジェクトを削除するのは難しい.
だから絶対にpointerやreferenceに戻ってlocal stackオブジェクトを指したり、heap-allocatedオブジェクトを指したりしないのもいい方法ではありません.コンパイラにオブジェクトをコピーさせるときは、コピーさせます.
いずれの場合も、参照を伝達することで値を返すことはできません.次のコードを見てください
const Rational& operator* (const Rational& r1, const Rational& r2){
Rational temp;
temp.numerator = r1.numerator * r2.numerator;
temp.denominator = r1.denominator * r2.denominator;
return temp;
}
実際には、この関数の戻り値に対する読み書き操作は、返されるオブジェクトが関数スタック内のオブジェクトであるため、関数が終了するとオブジェクトが破棄されるため、エラーを返します.破棄されたオブジェクトを使用するとエラーが発生します.
次に、スタックに割り当てる
const Rational& operator* (const Rational& r1, const Rational& r2){
Rational *temp = new Rational();
temp->numerator = r1.numerator * r2.numerator;
temp->denominator = r1.denominator * r2.denominator;
return *temp;
}
今度の呼び出し関数は正確に演算結果を返すことができるようになった.しかし、これは依然として問題のあるコードです.今回の問題はメモリ漏れです.*演算子を呼び出した後に発生したオブジェクトを削除する保証はありません.毎回演算結果オブジェクトをdeleteに落とすことに注意していますが、a=b*c*dを行います.この演算ではnew操作が2回行われ、その隠れたオブジェクトを削除するのは難しい.
だから絶対にpointerやreferenceに戻ってlocal stackオブジェクトを指したり、heap-allocatedオブジェクトを指したりしないのもいい方法ではありません.コンパイラにオブジェクトをコピーさせるときは、コピーさせます.