0

私は持っている

int * array=new int[2];

そして、最後の要素のメモリを解放したいので、割り当てられたメモリを1つの要素だけに減らします。電話してみた

delete array+1;

しかし、それはエラーを与えます

*** glibc が検出されました *** skuska: free(): 無効なポインター: 0x000000000065a020 *

明示的な再割り当てなしで C++03 でこれを行うことはできますか?

注: プリミティブ データ型 (int など) の代わりにクラスを使用したい場合、クラスのデストラクタも呼び出されるようにメモリを解放するにはどうすればよいですか?

注2:実装しようとしていますvector::pop_back

4

4 に答える 4

5

new[]これには表現を使用しないでください。それはベクトルの仕組みではありません。あなたがすることは、生メモリのチャンクを割り当てることです。これには malloc を使用するか、 new 式とは異なるoperator newを使用できます。デフォルトのアロケータを使用したと仮定すると、これは基本的に のreserve()メンバー関数が行うことです。std::vector式のように実際のオブジェクトを作成することはありませんnew[]

要素を構築する場合は、配置 newを使用して、割り当てた生メモリ内のどこかに場所を渡します。要素を破棄する場合は、そのデストラクタを直接呼び出します。delete[]完了したら、式を使用する代わりに、operator deleteif you usedoperator newを使用するか、 free()if you used を使用しmallocます。

以下は、10 個のオブジェクトを作成し、それらを逆の順序で破棄する例です。それらを任意の順序で破棄できますが、これはベクトル実装で行う方法です。

int main()
{
    void * storage = malloc(sizeof(MyClass) * 10);

    for (int i=0; i<10; ++i)
    {
        // this is placement new
       new ((MyClass*)storage + i) MyClass;
    }

    for (int i=9; i>=0; --i)
    {
        // calling the destructor directly
        ((MyClass*)storage + i)->~MyClass();
    }

    free(storage);
}

pop_back最後の要素のデストラクタを呼び出し、size メンバー変数を 1 減らすだけで実装されます。メモリを解放するべきではありません (また、不要なコピーを大量に作成しないと解放できません)。

于 2012-11-04T04:03:08.710 に答える
4

そのようなオプションはありません。配列のサイズを変更する唯一の方法は、 size で新しい配列を割り当てold_size - 1、古い配列の内容をコピーしてから、古い配列を削除することです。

自由なオブジェクト メモリが必要な場合は、ポインタの配列を作成してみませんか?

MyClass **arr = new MyClass*[size];
for(int i = 0; i < size; i++)
 arr[i] = new MyClass;

// ...

delete arr[size-1];
于 2012-11-04T03:03:54.167 に答える
3

std::vector::pop_back何も再割り当てしません — データサイズを決定する内部変数を更新し、それを 1 減らします。古い最後の要素はまだメモリ内にあります。ベクターでは、パブリック API を介してアクセスすることはできません。*

これは、再割り当ての増加が非線形であることと同様に、 がstd::vector::capacity()と同等でない理由の基礎ですstd::vector::size()

std::vectorしたがって、何らかの理由で本当に再発明しようとしている場合、再割り当てに関する質問への答えはdon'tです。


* 実際には、非プリミティブ データ型の場合はもう少し複雑です。そのような要素メモリが解放されなくても意味的に破棄されるからです。

于 2012-11-04T03:49:16.500 に答える
0

std::vectorC++03 を使用しているため、データ型にアクセスできます。それを使用すると、それは 1 つの呼び出しです。

#include <vector>
//...
std::vector<int> ary(3);
//...
ary.erase(ary.begin() + (ary.size() - 1));

また

#include <vector>
//...
std::vector<int> ary(3);
//...
ary.pop_back();

編集:

なぜ車輪を再発明しようとしているのですか?vector::pop_back を使用するだけです。

とにかく、デストラクタは、含まれているデータ型がポインターでない場合にのみ、含まれているデータ型で呼び出されます。削除するオブジェクトに対して手動で delete を呼び出す必要があるポインターである場合は、nullptrorに設定しNULLます (以前に削除されたオブジェクトに対して delete を呼び出すのは良くないため、null ポインターに対して delete を呼び出すことは非操作です)。消去を呼び出します。

于 2012-11-04T03:17:23.210 に答える