1

以下のサンプル コードを検討してください。このクラスDataは、データの配列を格納するために使用されます。簡単にするために、vector<char>データ メンバーとして を使用することにしました。ただし、これらのデータは、配列の最初の要素へのポインターと、もちろんこの配列の長さを必要とする外部ルーチンによって処理する必要があります。このため、関数get_data()とも実装しましたget_length()

class Data
{
public:
    Data(const char* sourcePtr, int sourceLength) : _data(sourcePtr, sourcePtr+sourceLength) { ; }

    const char* get_data() const { return &_data.front(); }
    int get_length() const { return _data.size(); }

    void print() const
    {
        vector<char>::const_iterator it;
        for(it = _data.begin(); it != _data.end(); ++it)
            cout << *it;
    }

private:
    vector<char> _data;
};

次に、クラスを使用する次のコード サンプルを考えてみましょうData

int main(int argc, char** argv)
{
    char* a = new char[4];
    a[0] = 'b';
    a[1] = 'y';
    a[2] = 't';
    a[3] = 'e';

    Data myData(a,4);
    delete[] a;

    myData.print();
    cout << endl;

    const char* aPtr = myData.get_data();

    // The following statement frees the memory allocated
    // for the data member of the class Data.
    delete[] aPtr;

    return 0;
}

上記のステートメントdelete[] aPtrは、クラスのデータ メンバーに割り当てられたメモリを解放しますData。その結果、myDataオブジェクトが自動的に割り当て解除されると、 の内容vector<char>は既に手動で割り当て解除されており、明らかにエラーSIGABRTが発生します。

コンパイラがステートメントdelete[] aPtrをエラーとして通知するようにするにはどうすればよいですか? Dataこの目標を達成するには、クラスをどのように変更する必要がありますか?

4

4 に答える 4

6

これに対処する最も簡単な方法は、ポインターの「所有者」が誰であるかを明確にすることです。私の C++ 時代には、ポインターが関数によって返された場合、関数の名前は "Get" ではなく "Create" で始まる必要がありました。後で、そのようなシナリオでは通常、スマート ポインターを返しました。

実際、ポインターを明示的に削除する必要のない C++ を書くのはまったく難しくありませんが、すべてのポインターをスマート ポインターに格納して、それ自体が破壊されたときにポインターを削除します。

于 2013-03-05T21:38:52.317 に答える
4

「裸の」操作を使用するのをやめnew、 RAII 型deleteでラップし、RAII 型のデストラクタを記述してnewいない限り使用しないでください。delete

std::unique_ptr<char[]> a{ new char[4] };
a[0] = 'b';
a[1] = 'y';
a[2] = 't';
a[3] = 'e';

Data myData(std::move(a),4);

このコードは、配列の所有権が明確にスマート ポインターに与えられ、その後、明確にDataオブジェクトに転送されることを意味します。配列を試みてdeleteもコンパイルされません。

これは後でユーザーが実行するのを妨げませんが、RAII 型のデストラクタ以外で使用しないdelete[] aPtrという習慣を身につけた場合、誰かが使用すべきではない場所を使用してバグを導入すると、それが明白になります。メモリを所有します。deletedelete

むき出しのポインターをいじるのはやめましょう。あなたのコードのユーザーがそうするのをやめないなら、彼らに難しい方法を学ばせてください。

于 2013-03-05T22:00:53.420 に答える
1

適切なドキュメントを作成します。他のプログラマーが愚かなことをするのを防ぐのはあなたの仕事ではありません。

于 2013-03-05T21:51:27.303 に答える
1

あなたはそうしない。 new誰がポインタを所有しているかを追跡しdeleteません。それがあなたの仕事です。

代わりにできることは、ポインターが指すデータのコピーを作成することです。次に、呼び出し元がその配列で何をするかは問題ではありません。あなたは自分のコピーを持っていて、それを欲しがる人に公開するような頭がおかしいことをしていないと仮定すれば、それは安全です。

または、チェックアウトしstd::unique_ptrstd::shared_ptr. :P メモリ管理に関する限り、それらは新しい話題です。スマート ポインターを使用すると、メモリはほとんど自己管理します。

于 2013-03-05T21:36:14.033 に答える