「オブジェクトポインタ,newとdelete」の編集履歴(バックアップ)一覧はこちら
「オブジェクトポインタ,newとdelete」(2016/03/23 (水) 13:25:37) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
*オブジェクトポインタとは
※こちらも参照 [[オブジェクト]]
通常のポインタと同様、クラスに対してもポインタで扱うことができる。
クラス型のポインタpはobjを指すようになる。
Person obj;
Person *p = &obj;
ポインタの場合、各変数や関数にアクセスする時は
下の例のように->(アロー演算子)を使用する。
p->age;
p->selfIntroduction();
*メモリの動的確保と解放(malloc & free、 new & delete)
**new 演算子
C、C++の配列は動的な配列の確保ができない。
new演算子を使うとメモリの動的確保が可能になる。
new,deleteはC++ の演算子なのでincludeの必要はない。
cの<stdlib.h>にあるmalloc と freeでも使用可能
ただし、演算子オーバーロードが使えない、コンストラクタ、デストラクタが呼び出せないため、C++ではnew と deleteを使う。
例:
double a[10]; // 静的な確保はOK
int n;
cin >> n; // キーボードから入力
double b[n]; // NG コンパイルエラーになる
mallocの詳細
形式: #include <stdlib.h>
void *malloc(size_t size);
機能: 大きさsizeのメモリ領域を確保する。
引数: size: 確保したいメモリのバイトサイズ。
返却値: 成功した時:確保したメモリブロックを示すポインタ
失敗した時:NULL
例1:mallocによる動的確保とfreeによる領域解放
#html2(){{
<pre class="brush: cpp;">
#include < iostream >
using namespace std;
int main(void) {
int *ip; /* 割り振られた領域のアドレスを格納するためのint型のポインタipを宣言 */
int n;
/* 確保する要素数を入力 */
cout << "要素数を入力してください: " <<endl;
cin >> n;
ip = (int *)malloc(n * sizeof(int)); /* メモリ領域の確保 */
for (int i=0; i < n; i++){
ip[i] = i;
}
for (int i=0;i < n; i++)
cout<< ip[i] << endl;
free(ip); /* 確保したメモリ領域の解放 */
return 0;
}
</pre>
}}
例2:newによる動的確保とdeleteによる領域確保
#html2(){{
<pre class="brush: cpp;">
#include < iostream >
using namespace std;
int main(void){
int n;
cin >> n;
int * b = new int[n]; // b を確保
for(int i=0; i < n; i++){
b[i]=i;
}
for(int i=0; i < n; i++){
cout<< b[i] << endl;
}
delete[] b; // b を解放
return 0;
}
</pre>
}}
*二次元配列の場合の動的確保
通常の二次元配列(b[][])だと動的確保ができないので、ポインタ配列を使って擬似的に作り出します。
以下がソースコードです。
#html2(){{
<pre class="brush: cpp;">
#include < iostream >
using namespace std;
int main(void){
int n,m;
cin >> n;
cin >> m;
//二次元の時はダブルポインタ(** a)を使用
double ** a = new double*[n]; //n個のポインタ型のdouble型配列確保
for( int i=0; i < n; i++ ) {
a[i] = new double[m]; //一つ前で作った要素数nの配列をm個確保
}
for(int i=0; i < n; i++){
for(int j=0; j < m; j++){
a[i][j]=j;
}
}
for(int i=0; i < n; i++){
for(int j=0; j < m; j++){
cout<<a[i][j]<<endl;
}
}
for( int i=0; i < n; i++ ) {
delete[] a[i]; //deleteで開放。
}
delete[] a; //deleteで開放
return 0;
}
</pre>
}}
*クラスのオブジェクトの動的確保について
※クラスのオブジェクトの場合、標準入力からのオブジェクトの動的確保はできません。
動的確保ができないので、set関数を使ってnewした後に値を与えます。
**Person.h
#html2(){{
<pre class="brush: cpp;">
#include < string >
using namespace std;
class Person{
private:
string name;
int age;
float height;
float weight;
int id; //人を識別するためのID
static int sum_person; //Personオブジェクトの総数保存変数
public:
Person(void);
~Person(void);
void setStatus(); //set関数
void selfIntroduction();
};
</pre>
}}
**Person.cpp
#html2(){{
<pre class="brush: cpp;">
#include "Person.h"
#include < iostream >
int Person::sum_person=0; //static変数
//デフォルトコンストラクタ
Person::Person(void){
Person::sum_person++; //総数+1
this->id=sum_person; //現在の総数をIDとして代入
}
//デストラクタ
Person::~Person(void){
}
void Person::setStatus(){
cout<<"ID:"<<this->id<<"のデータを入力します。"<< endl;
cout<<"名前を入力:"<<endl;
cin >> this->name;
cout<<"年齢を入力:"<<endl;
cin >> this->age;
cout<<"身長を入力:"<<endl;
cin >> this->height;
cout<<"体重を入力:"<<endl;
cin >> this->weight;
cout<<"データの入力が完了しました。"<<endl;
}
void Person::selfIntroduction(){
cout << "私の名前は" << this->name<<"です。"<<endl;
cout <<"年齢は"<<this->age<<"歳で、身長は"<<this->height <<"cmで、体重は"<<this->weight << "kgです。" << endl;
}
</pre>
}}
**main.cpp
#html2(){{
<pre class="brush: cpp;">
#include "Person.h"
#include < iostream >
using namespace std;
int main(){
const int NUM=3;
Person *p[NUM];
for(int i=0; i < NUM; i++){
p[i]=new Person();//Person型オブジェクトpをnum個作成
}
for(int i=0; i < NUM; i++){
p[i]->setStatus();
}
for(int i=0; i < NUM; i++){
p[i]->selfIntroduction();
}
return 0;
}
</pre>
}}
memo
※static変数は、明示的に初期値を与えなかった場合には、自動的に 0 で初期化される。
※インスタンスを生成しなくても、静的メンバ変数だけは存在している。
※静的メンバ変数を宣言した場合、その実体の定義をクラス定義の外側に記述する必要がある。
cpp の"include の下あたりに クラス名::変数名=値;で定義する。
*問題
**問題1
HumanとBoxの2つのクラスを作成しmainでオブジェクトを2つ生成せよ。
HumanとBoxは下記の仕様で作成せよ。
Humanクラス
private
性質:string型 name
public
操作:putBall
返り値:なし
引数1 :整数型 num(玉を入れる個数)
引数2 :Box型 *b (どのBoxに入れるか)
指定された (Box b) に引数1で指定した(num)個ボールを入れる操作を行う
コンストラクタ
引数:string name
引数を使ってnameをセットする。
Boxクラス
private
性質:整数型 capacity(容量)
:整数型 ballnum(持っているボールの個数)
public
操作:addBall
返り値:なし
引数1:整数型 num
num個持っているボールを持っているボールの個数に加算する。
容量以上のボールはあふれるように処理し、溢れたことを標準出力でユーザに伝える。
:dispBallnum
返り値:なし
引数:なし
現在のボール個数を画面に出力する。
コンストラクタ
引数1 整数型 capacity
引数2 整数型 ballnum
引数を使って箱の容量と入っているボール個数の初期値をセットする。
main
Human(taro,jiro)とBox(b1,b2)のオブジェクトを2つ生成
b1:初期値は容量10,現在のボール数0
b2:初期値は容量20,現在のボール数5
各Boxの現在の個数を標準出力
taroはb1に玉を10個入れる
jiroはb2に玉を15個入れる
各Boxの現在の個数を標準出力
taroはb2に玉を10個入れる
jiroはb1に玉を15個入れる
各Boxの現在の個数を標準出力
生成したオブジェクトを削除
プログラム終了
//#include(highlight)
testcounter
合計 &counter(total)
今日 &counter(today)
昨日 &counter(yesterday)
*オブジェクトポインタとは
※こちらも参照 [[オブジェクト]]
通常のポインタと同様、クラスに対してもポインタで扱うことができる。
クラス型のポインタpはobjを指すようになる。
Person obj;
Person *p = &obj;
ポインタの場合、各変数や関数にアクセスする時は
下の例のように->(アロー演算子)を使用する。
p->age;
p->selfIntroduction();
*メモリの動的確保と解放(malloc & free、 new & delete)
**new 演算子
C、C++の配列は動的な配列の確保ができない。
new演算子を使うとメモリの動的確保が可能になる。
new,deleteはC++ の演算子なのでincludeの必要はない。
cの<stdlib.h>にあるmalloc と freeでも使用可能
ただし、演算子オーバーロードが使えない、コンストラクタ、デストラクタが呼び出せないため、C++ではnew と deleteを使う。
例:
double a[10]; // 静的な確保はOK
int n;
cin >> n; // キーボードから入力
double b[n]; // NG コンパイルエラーになる
mallocの詳細
形式: #include <stdlib.h>
void *malloc(size_t size);
機能: 大きさsizeのメモリ領域を確保する。
引数: size: 確保したいメモリのバイトサイズ。
返却値: 成功した時:確保したメモリブロックを示すポインタ
失敗した時:NULL
例1:mallocによる動的確保とfreeによる領域解放
#html2(){{
<pre class="brush: cpp;">
#include < iostream >
int main(void) {
using namespace std;
int *ip; /* 割り振られた領域のアドレスを格納するためのint型のポインタipを宣言 */
int n;
/* 確保する要素数を入力 */
cout << "要素数を入力してください: " <<endl;
cin >> n;
ip = (int *)malloc(n * sizeof(int)); /* メモリ領域の確保 */
for (int i=0; i < n; i++){
ip[i] = i;
}
for (int i=0;i < n; i++)
cout<< ip[i] << endl;
free(ip); /* 確保したメモリ領域の解放 */
return 0;
}
</pre>
}}
例2:newによる動的確保とdeleteによる領域確保
#html2(){{
<pre class="brush: cpp;">
#include < iostream >
int main(void){
using namespace std;
int n;
cin >> n;
int * b = new int[n]; // b を確保
for(int i=0; i < n; i++){
b[i]=i;
}
for(int i=0; i < n; i++){
cout<< b[i] << endl;
}
delete[] b; // b を解放
return 0;
}
</pre>
}}
*二次元配列の場合の動的確保
通常の二次元配列(b[][])だと動的確保ができないので、ポインタ配列を使って擬似的に作り出します。
以下がソースコードです。
#html2(){{
<pre class="brush: cpp;">
#include < iostream >
int main(void){
using namespace std;
int n,m;
cin >> n;
cin >> m;
//二次元の時はダブルポインタ(** a)を使用
double ** a = new double*[n]; //n個のポインタ型のdouble型配列確保
for( int i=0; i < n; i++ ) {
a[i] = new double[m]; //一つ前で作った要素数nの配列をm個確保
}
for(int i=0; i < n; i++){
for(int j=0; j < m; j++){
a[i][j]=j;
}
}
for(int i=0; i < n; i++){
for(int j=0; j < m; j++){
cout<<a[i][j]<<endl;
}
}
for( int i=0; i < n; i++ ) {
delete[] a[i]; //deleteで開放。
}
delete[] a; //deleteで開放
return 0;
}
</pre>
}}
*クラスのオブジェクトの動的確保について
※クラスのオブジェクトの場合、標準入力からのオブジェクトの動的確保はできません。
動的確保ができないので、set関数を使ってnewした後に値を与えます。
**Person.h
#html2(){{
<pre class="brush: cpp;">
#include < string >
class Person{
private:
std::string name;
int age;
float height;
float weight;
int id; //人を識別するためのID
static int sum_person; //Personオブジェクトの総数保存変数
public:
Person(void);
~Person(void);
void setStatus(); //set関数
void selfIntroduction();
};
</pre>
}}
**Person.cpp
#html2(){{
<pre class="brush: cpp;">
#include "Person.h"
#include < iostream >
using namespace std;
int Person::sum_person=0; //static変数
//デフォルトコンストラクタ
Person::Person(void){
Person::sum_person++; //総数+1
this->id=sum_person; //現在の総数をIDとして代入
}
//デストラクタ
Person::~Person(void){
}
void Person::setStatus(){
cout<<"ID:"<<this->id<<"のデータを入力します。"<< endl;
cout<<"名前を入力:"<<endl;
cin >> this->name;
cout<<"年齢を入力:"<<endl;
cin >> this->age;
cout<<"身長を入力:"<<endl;
cin >> this->height;
cout<<"体重を入力:"<<endl;
cin >> this->weight;
cout<<"データの入力が完了しました。"<<endl;
}
void Person::selfIntroduction(){
cout << "私の名前は" << this->name<<"です。"<<endl;
cout <<"年齢は"<<this->age<<"歳で、身長は"<<this->height <<"cmで、体重は"<<this->weight << "kgです。" << endl;
}
</pre>
}}
**main.cpp
#html2(){{
<pre class="brush: cpp;">
#include "Person.h"
#include < iostream >
int main(){
using namespace std;
const int NUM=3;
Person *p[NUM];
for(int i=0; i < NUM; i++){
p[i]=new Person();//Person型オブジェクトpをnum個作成
}
for(int i=0; i < NUM; i++){
p[i]->setStatus();
}
for(int i=0; i < NUM; i++){
p[i]->selfIntroduction();
}
return 0;
}
</pre>
}}
memo
※static変数は、明示的に初期値を与えなかった場合には、自動的に 0 で初期化される。
※インスタンスを生成しなくても、静的メンバ変数だけは存在している。
※静的メンバ変数を宣言した場合、その実体の定義をクラス定義の外側に記述する必要がある。
cpp の"include の下あたりに クラス名::変数名=値;で定義する。
*問題
**問題1
HumanとBoxの2つのクラスを作成しmainでオブジェクトを2つ生成せよ。
HumanとBoxは下記の仕様で作成せよ。
Humanクラス
private
性質:string型 name
public
操作:putBall
返り値:なし
引数1 :整数型 num(玉を入れる個数)
引数2 :Box型 *b (どのBoxに入れるか)
指定された (Box b) に引数1で指定した(num)個ボールを入れる操作を行う
コンストラクタ
引数:string name
引数を使ってnameをセットする。
Boxクラス
private
性質:整数型 capacity(容量)
:整数型 ballnum(持っているボールの個数)
public
操作:addBall
返り値:なし
引数1:整数型 num
num個持っているボールを持っているボールの個数に加算する。
容量以上のボールはあふれるように処理し、溢れたことを標準出力でユーザに伝える。
:dispBallnum
返り値:なし
引数:なし
現在のボール個数を画面に出力する。
コンストラクタ
引数1 整数型 capacity
引数2 整数型 ballnum
引数を使って箱の容量と入っているボール個数の初期値をセットする。
main
Human(taro,jiro)とBox(b1,b2)のオブジェクトを2つ生成
b1:初期値は容量10,現在のボール数0
b2:初期値は容量20,現在のボール数5
各Boxの現在の個数を標準出力
taroはb1に玉を10個入れる
jiroはb2に玉を15個入れる
各Boxの現在の個数を標準出力
taroはb2に玉を10個入れる
jiroはb1に玉を15個入れる
各Boxの現在の個数を標準出力
生成したオブジェクトを削除
プログラム終了
//#include(highlight)
testcounter
合計 &counter(total)
今日 &counter(today)
昨日 &counter(yesterday)
表示オプション
横に並べて表示:
変化行の前後のみ表示: