1
#include <stdio.h>
#include <iostream>
#include <string>


using namespace std;

class myClass{

public:
    int *num1;
    myClass();


};

myClass::myClass(){
    num1 = new int[1];
    num1[0] = 10;
}


int main()
{
    myClass *myclass;

    myclass = new myClass[10];

    cout << myclass[0].num1[0] << endl;

    delete &myclass[0];
    cout << myclass[0].num1[0] << endl;

}

myclass (myclass[0]) の最初のインスタンスを削除したい。

このコードは正しく実行されません。削除部分で失敗します。おそらく私が見逃しているものがあります。

私は何を間違えましたか?

4

2 に答える 2

2

で作成された配列の一部だけを削除することはできませんnewnewすべて一緒にしかdelete編集できないメモリのブロックを割り当てます。

オブジェクトがそれ自体の内部データを解放するようにしたい場合は、クラスを調整する必要があります。クラスは、それ自体を実行するために、それ自体の内部リソースをカプセル化して非表示にする必要があります。

割り当てた配列を保持するメモリの小さなブロックが必要な場合は、小さなブロックを割り当て、保持する内容を新しいブロックに移動してから、古いブロック全体を削除する必要があります。

int *arr = new int[10];

int *tmp = new int[9];
std::copy(arr+1, arr+10, tmp);
delete [] arr;
arr = tmp;

独自のリソースを管理し、コピーまたは移動を処理するようにクラスを設計する必要があります。現在myClassは配列を割り当てていますが、クリーンアップを処理するために他のコードに依存しています。これを実行するのに適した方法ではありません。正しいことを実行するのに適したコードが他にない場合が多く、場合によっては間違いを犯すことが非常に多いためです。

コンストラクタで割り当てているので、割り当て解除を処理するデストラクタが必要です。そして、3つの特別な操作(copy-ctor、copy-assignment、destructor)のいずれかを実装するので、それらすべての実装を検討する必要があります。(これは「三つのルール」と呼ばれます。C++ 11では、ムーブ代入とムーブ代入が追加された「三つのルール」になります。)

class myClass {
public:
    myClass();

    // destructor to handle destroying internal resources correctly
    ~myClass();

    // copy constructor and copy assignment operator, to handle copying correctly
    myClass(myClass const &rhs);
    myClass &operator=(myClass const &rhs);

    // move constructor and move assignment operator, to handle moves correctly (C++11)
    myClass(myClass && rhs);
    myClass &operator= (myClass &&rhs);

private:
   int *num1; // private so external code can't screw it up

public:
   // limited access to num1
   int size() const { if (num1) return 1; else return 0; }
   int &operator[] (size_t i) { return num1[i]; }
};

コンストラクターを実装したのと同じように実装することも、初期化子リストとC++11の統一初期化を使用することもできます。

myClass::myClass() : num1(new int[1]{10}) {}

ここで、必要なデストラクタは、クラスに持たせたいセマンティクスと、維持したい特定の不変条件によって異なります。「値」セマンティクスはC++の標準です(JavaまたはC#に精通している場合、これらの言語はユーザー定義型の「参照」セマンティクスを推奨または要求します)。値のセマンティクスが必要な場合、およびnum1が常にメモリを所有するか、nullであるという不変条件を維持する場合に使用できる、デストラクタを次に示します。

myClass::~myClass() { delete num1; }

コピーと移動はさまざまな方法で処理できます。それらを完全に禁止したい場合は、(C ++ 11で)次のように言うことができます。

myClass::myClass(myClass const &rhs) = delete;
myClass &myClass::operator=(myClass const &rhs) = delete;

myClass::myClass(myClass && rhs) = delete;
myClass &myClass::operator= (myClass &&rhs) = delete;

または、コピーや移動を許可する(そして、上記の値のセマンティクスと不変条件を維持する)場合は、これらの関数のペアのいずれかまたは両方を実装できます。

myClass::myClass(myClass const &rhs) : num1( rhs.size() ? new int[1]{rhs[0]} : nullptr) {}
myClass &myClass::operator=(myClass const &rhs) {
    if (num1)
        num1[0] = rhs[0];
}

myClass::myClass(myClass && rhs) : num1(rhs.num1) { rhs.num1 = nullptr; } // remember to maintain the invariant that num1 owns the thing it points at, and since raw pointers don't handle shared ownership only one thing can own the int, and therefore only one myClass may point at it. rhs.num1 must be made to point at something else...
myClass &myClass::operator= (myClass &&rhs) { std::swap(num1, rhs.num1); } // steal rhs.num1 and leave it to rhs to destroy our own num1 if necessary. We could also destroy it ourselves if we wanted to.

intこの実装により、myClassオブジェクトをまたは他の「値」型と同じように扱うことができるようになりました。内部リソースの管理について心配する必要はもうありません。それ自体が面倒を見てくれます。

int main() {
    std::vector<myClass> myclassvec(10);

    cout << myclassvec[0][0] << '\n';

    myclassvec.erase(myclassvec.begin()); // erase the first element

    cout << myclassvec[0][0] << '\n'; // access the new first element (previously the second element);
}
于 2012-11-18T07:46:52.710 に答える
1

プライベートメンバーの削除を処理するクラス内に関数を作成します。おそらく呼び出されますFreeMem(int index)

void myClass::FreeMem()
{
    delete [] num1
}

しかし正直なところ、この種のプログラムでデストラクタを使用せずにオブジェクトのメモリを解放することは危険であり、まったく悪い習慣です。デストラクタでメモリを解放することをお勧めします。オブジェクトが終了すると、メモリが解放されます。

myClass::~myClass()
{
    delete [] num1;
}

注意すべきもう 1 つの点は、動的変数に値を 1 つだけ作成する場合は、次のように記述する方が簡単です。

int * pnum = new int;
//or in your class..
pnum = new int;

とりわけ、あなたのプログラムには多くの欠陥があります。クラスについてもう一度読み直すことをお勧めします。

于 2012-11-18T06:05:10.823 に答える