C++のnewとdelete
19446 ワード
一、newとdelete:
(1)newはオペレータであり,関数ではなくmallocは関数である.
(2)基本データ型(int,float,double,char),free,malloc,new,deleteの効果は一致する.
(3)delete,freeは基本データ型に対して,2回解放してもエラーが発生する.
(4)freeの後、ポインタの値は変わらず、deleteの後、ポインタの値は変わる(私のパソコンではdeleteのたびにポインタの値が0000 8123になった)が、freeの後のポインタの値は変わらず、印刷されたのはゴミ値である.freeの後、迷路ポインタを避けるために、ポインタを空ポインタ(nullptr)に設定したほうがよい.
(5)基本データ型newであればコンストラクション関数は呼び出されず,deleteではコンストラクション関数は呼び出されない.
構造タイプの場合、newはコンストラクション関数を呼び出し、deleteはコンストラクション関数を呼び出します.
(6)基本データ型配列,delete,delete[]一致;基本データ型,互いに混合して使用できる.
(7)複合データ型(delete,delete[]は混在できない)
例:mydata*p(new mydata); delete p;
mydata *p(new mydata[10]); delete[] p;
(8)個々のスタック上のオブジェクトは,delete[]を用いることができず,deleteを繰り返すことができず,次のdeletコードは誤りであり,delete pのみを用いることができ,delete[]pを用いることができない.
mydata *p(new mydata);
delete [ ] p;//単一のスタック上のオブジェクトはdelete[]を使用してはいけません.delete[]プログラムを使用するとエラーが発生します.
二、位置決めnew演算子:
位置決めnew演算子はnew演算子の変形です.通常、newはメモリを開くためにスタック領域にあり、必要に応じてnewはスタック領域と静的領域にも空間を開くことができる.
位置決めnew演算子を使用するには、newヘッダファイル#includeを含めます.
実行結果:
new演算子を位置決めし、p 2を配列bufferに配置し、p 2とbufferのアドレスは01380320である.しかし、彼らのタイプは異なり、p 2はdoubleのポインタであり、bufferはcharのポインタである.だからvoid*でbufferをタイプ変換して、さもなくばbufferは1つの文字を印刷します.
最後に、bufferはメモリの静的メモリを指定するため、deleteはスタック領域の割り当てられたメモリしか解放できません.
(1)newはオペレータであり,関数ではなくmallocは関数である.
(2)基本データ型(int,float,double,char),free,malloc,new,deleteの効果は一致する.
(3)delete,freeは基本データ型に対して,2回解放してもエラーが発生する.
(4)freeの後、ポインタの値は変わらず、deleteの後、ポインタの値は変わる(私のパソコンではdeleteのたびにポインタの値が0000 8123になった)が、freeの後のポインタの値は変わらず、印刷されたのはゴミ値である.freeの後、迷路ポインタを避けるために、ポインタを空ポインタ(nullptr)に設定したほうがよい.
(5)基本データ型newであればコンストラクション関数は呼び出されず,deleteではコンストラクション関数は呼び出されない.
構造タイプの場合、newはコンストラクション関数を呼び出し、deleteはコンストラクション関数を呼び出します.
(6)基本データ型配列,delete,delete[]一致;基本データ型,互いに混合して使用できる.
(7)複合データ型(delete,delete[]は混在できない)
例:mydata*p(new mydata); delete p;
mydata *p(new mydata[10]); delete[] p;
(8)個々のスタック上のオブジェクトは,delete[]を用いることができず,deleteを繰り返すことができず,次のdeletコードは誤りであり,delete pのみを用いることができ,delete[]pを用いることができない.
mydata *p(new mydata);
delete [ ] p;//単一のスタック上のオブジェクトはdelete[]を使用してはいけません.delete[]プログラムを使用するとエラーが発生します.
#include<iostream>
using namespace std;
void main2()
{
int *p1 = new int(4);//
int *p2 = new int[10]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };//
delete p1;//delete p1 int *p1 = new int(4);
delete[] p2;//delete[] p2 int *p2 = new int[10]{ 1,2,3,4,5,6,7,8,9,0 };
cin.get();
}
// new
void main3()
{
int *p = new int[10]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
cout << p << endl;
cout << "--------------" << endl;
delete[] p;
cin.get();
}
// new
void main4()
{
int *p1 = new int(4);
cout << p1 << endl;
cout << "--------------" << endl;
delete p1;//delete[] p1;
cin.get();
}
class mydata
{
public:
mydata() //
{
cout << "create" << endl;
}
~mydata()//
{
cout << "delete" << endl;
}
};
void main()
{
mydata *p(new mydata);
delete p;
//mydata *p(new mydata);
//delete []p;// , delete [], delete
mydata *p(new mydata[10]);
delete []p;//
cin.get();
}
二、位置決めnew演算子:
位置決めnew演算子はnew演算子の変形です.通常、newはメモリを開くためにスタック領域にあり、必要に応じてnewはスタック領域と静的領域にも空間を開くことができる.
位置決めnew演算子を使用するには、newヘッダファイル#include
#include <iostream>
#include <new>
using namespace std;
const int BUF = 512;
const int N = 5;
char buffer[BUF];
int main()
{
double *p1, *p2;
cout << "calling new and placement new " << endl;
p1 = new double[N];
p2 = new (buffer) double[N];
for (int i = 0; i < N; i++)
{
p2[i] = p1[i] = 1000 + 10.0*i;
}
cout << "heap:"<<p1<< " static:"<<(void*)buffer << endl;
cout << "memory contents:" << endl;
for (int i = 0; i < N;i++)
{
cout <<" p1 "<< p1[i] << " at " << &p1[i] << "; ";
cout << " p2 "<<p2[i] << " at " << &p2[i] << endl;
}
cout << " " << endl;
cout << "calling new and placement new a second time" << endl;
double *p3, *p4;
p3 = new double[N];
p4 = new (buffer) double[N];//
for (int i = 0; i < N; i++)
{
p4[i] = p3[i] = 1000 + 50.0*i;
}
cout << "memory contents:" << endl;
for (int i = 0; i < N; i++)
{
cout << "p3 "<<p3[i] << " at " << &p3[i] << "; ";
cout << "p4 " << p4[i] << " at " << &p4[i] << endl;
}
cout << " " << endl;
cout << "calling new and placement new a third time" << endl;
delete [] p1;
p1 = new double[N];
p2 = new(buffer + N*sizeof(double)) double[N];
for (int i = 0; i < N; i++)
{
p2[i] = p1[i] = 1000 + 70.0*i;
}
cout << "memory contents:" << endl;
for (int i = 0; i < N; i++)
{
cout <<"p1 "<< p1[i] << " at " << &p1[i] << "; ";
cout << "p2"<<p2[i] << " at " << &p2[i] << endl;
}
delete[]p1;
delete[]p3;
cin.get();
return 0;
}
実行結果:
calling new and placement new
heap:007AB2F8 static:01380320
memory contents:
p1 1000 at 007AB2F8; p2 1000 at 01380320
p1 1010 at 007AB300; p2 1010 at 01380328
p1 1020 at 007AB308; p2 1020 at 01380330
p1 1030 at 007AB310; p2 1030 at 01380338
p1 1040 at 007AB318; p2 1040 at 01380340
calling new and placement new a second time
memory contents:
p3 1000 at 007AB500; p4 1000 at 01380320
p3 1050 at 007AB508; p4 1050 at 01380328
p3 1100 at 007AB510; p4 1100 at 01380330
p3 1150 at 007AB518; p4 1150 at 01380338
p3 1200 at 007AB520; p4 1200 at 01380340
calling new and placement new a third time
memory contents:
p1 1000 at 007AB2F8; p21000 at 01380348
p1 1070 at 007AB300; p21070 at 01380350
p1 1140 at 007AB308; p21140 at 01380358
p1 1210 at 007AB310; p21210 at 01380360
p1 1280 at 007AB318; p21280 at 01380368
new演算子を位置決めし、p 2を配列bufferに配置し、p 2とbufferのアドレスは01380320である.しかし、彼らのタイプは異なり、p 2はdoubleのポインタであり、bufferはcharのポインタである.だからvoid*でbufferをタイプ変換して、さもなくばbufferは1つの文字を印刷します.
最後に、bufferはメモリの静的メモリを指定するため、deleteはスタック領域の割り当てられたメモリしか解放できません.