5

メモリを動的に割り当てるクラスを設計しているときに、メモリ割り当てに関する次の問題に遭遇しました。クラスをより良い方法で設計する方法について、あなたの何人かが私を正しい方向に向けることができることを望んでいました. 私のクラスはメモリを動的に割り当てるため、デストラクタでも削除します。

問題を説明するために、次のばかげたクラス宣言を考えてみましょう。

class testClass{
    int* data;
public:
    testClass(){
        data = new int;
        *data = 5;
    }
    ~testClass(){
        delete data;
    }
};

ここまでは順調ですね。ここで、これらのオブジェクトの 1 つをメインに作成するとします。

int main(){
    testClass myObject;
    return 0;
}

もちろんまだ問題はありません。しかし、testClass オブジェクトを入力として受け取る関数を作成し、これを main から呼び出すとします。

void doNoting(testClass copyOfMyObject){
    //do nothing
}
int main(){
    testClass myObject;
    doNothing(myObject);
    return 0;
}

今回は、この関数はローカル変数 copyOfMyObject を作成しますが、これは単に myObject のコピーです。次に、その関数の最後に到達すると、そのローカル オブジェクトのデストラクタが自動的に呼び出され、データ ポインタが指すメモリが削除されます。ただし、これは myObject のデータ ポインタが指しているメモリと同じであるため、myObject のメモリは処理中に誤って削除されてしまいます。私の質問は、クラスを設計するためのより良い方法は何ですか?

4

3 に答える 3

7

を呼び出すと、値によって渡されるためdoNothing()、オブジェクトのコピーが作成されます。testClass残念ながら、このコピーが破棄されると、デストラクタが呼び出さdataれ、 の元のインスタンスで使用されていたものと同じものが削除されますtestClass

「コピーコンストラクター」と「参照渡し」について学びたい。つまり、クラスのコピー コンストラクターを定義して、インスタンスのコピーが作成されるときに、そのdataメンバーに独自のメモリを割り当てる必要があります。また、値で渡すのではなく、へのポインタまたは参照を渡して、doNothing()コピーが作成されないようにすることもできます。

于 2013-03-05T18:39:02.943 に答える
2

次の形式のコンストラクターであるコピーコンストラクターを作成する必要があります。

testClass::testClass(const testClass &o)
{ 
    // appropriate initialization here
}

あなたの場合、「適切な初期化」とは、メモリの新しいチャンクを割り当て、古いチャンクから新しいチャンクにメモリをコピーすることを意味する場合があります。または、参照カウントを行うことを意味する場合があります。または何でも。

また、ここStackOverflowで三つのルールの詳細を読む必要があります!

于 2013-03-05T18:40:27.883 に答える
0

当局からのガイドラインは次のとおりです。 {デストラクタ、代入演算子、コピーコンストラクタ}のいずれかを持つクラスには、通常、3つすべてが必要です。

データに新しく割り当てられたintを作成するコピーコンストラクターが必要です。これにより、データは破棄されますが、元のintには影響しません。

または、空白のプライベートコピーコンストラクターを作成して、それを効果的に無効にしたり、ユーザーに参照渡しを強制したり、コピーを行わない別の方法を実行したりすることもできます。

于 2013-03-05T18:41:46.497 に答える