静岡理工科大学 菅沼ホーム 全体目次 演習解答例 付録 索引

第12章 代入と初期化

  1. 12.1 代入
  2. 12.2 初期化
    1. (プログラム例 12.1 ) 代入と初期化
    2. (プログラム例 12.2 ) 代入と初期化の解決( = のオーバーロード)
    3. (プログラム例 12.3 ) 行列の乗算

12.1 代入

  初期化とは,まだ何も値の入っていないオブジェクトに値を設定することであり,また,代入とは,オブジェクトが記憶している値を捨てて新しい値と置き換えることです.new 演算子によってメモリを確保していないようなオブジェクトにおいては,いずれの場合も期待したとおりに働き,特に気にかける必要はありません.

  ここで,「期待したとおり」というのは以下のような意味です.例えば,a を b に代入したとします( a,b: クラスや基本型の変数).当然,a の値と b の値は等しくなり,かつ,代入後,a( b )の値を変化させたても,b( a )の値に影響を与えないといった意味です.プログラム例 12.1 とその実行結果を見てください.Complex 型および Vector1 型の変数に対しては,期待通りの結果が得られています.代入の際,a の値のコピーが b に代入されるわけですから,当然の結果です.

  ただし,ポインタを使用している場合(例えば,new 演算子を使用しているような場合)は,次節で述べる初期化の場合と同様,注意が必要です.プログラム例 12.1 において,Vector2 型の変数 v4 を v3 に代入しています.代入後は,結果からも明らかなように,v3 と v4 は全く同じ値になっています.ところが,v4 の n を 5 に,また,v4 の x[0] を 1.5 に変化させた場合の結果を見てください.n については期待通りの結果となっていますが,x[0] の値は,v4 だけでなく v3 においても変化しています.

  これは,v4 の x(アドレス)のコピーが v3 の x に代入されるため,v3 と v4 の x が同じ領域を指しているためです.もちろん,このままの状態でも,同じ領域 を指していることを認識し,かつ,v3 および v4 の使用上,不都合がなければ特に問題ありません.しかし,使用上不都合である場合も多く存在します.さらに,プログラム例 12.1 ではコメントになっており実行されていませんが,このコメントをはずし,デストラクタを実行するようにすると実行時のエラーが出てしまいます.デストラクタは,v3 と v4 が不必要になった時点で起動します.まず,最初に,v3 に対してデストラクタが起動されたとします.この際は,特に問題は起こりません.しかし,次に v4 に対してデストラクタが起動されたとき,既に v3 に対するデストラクタによって削除された x に対する領域を再度削除しようとします.これが,実行時におけるエラーの原因です.

  上に述べた問題を解決するための手段の一つが,プログラム例 12.2 のように,代入演算子をオーバーロードする方法です.代入演算子のオーバーロードにおいては,既にある領域を開放し,新しい領域を確保し,かつ,そこに代入するデータをコピーしています.

12.2 初期化

  プログラム例 12.1 の初期化の部分を見てください.代入の場合と同様,Complex 型や Vector1 型の変数に対しては,
	Complex c3 = c4;
	Vector1 v5 = v6;
		
の初期化によって,特に問題となるようなことは発生しません.ところが,Vector2 型の変数に対しては,代入の場合と同様の問題が発生してしまいます.この問題も,プログラム例 12.2 のように,初期化のためのコンストラクタを定義することによって回避可能です.

(プログラム例 12.1 ) 代入と初期化 

/****************************/
/* 代入と初期化             */
/*      coded by Y.Suganuma */
/****************************/
#include <iostream>

/***********************/
/* クラスComplexの定義 */
/***********************/
class Complex {
	public:
		double r, i;
		Complex (double r1, double i1)	 // コンストラクタ
		{
			r = r1;
			i = i1;
		}
};

/***********************/
/* クラスVector1の定義 */
/***********************/
class Vector1 {
	public:
		int n;
		double x[2];
		Vector1 (int n1, double x1, double x2)	 // コンストラクタ
		{
			n    = n1;
			x[0] = x1;
			x[1] = x2;
		}
};

/***********************/
/* クラスVector2の定義 */
/***********************/
class Vector2 {
	public:
		int n;
		double *x;
		Vector2 (int n1, double x1, double x2)	 // コンストラクタ
		{
			n    = n1;
			x    = new double [2];
			x[0] = x1;
			x[1] = x2;
		}
//		~Vector2 () {delete [] x;}   // デストラクタ
};

/************/
/* main関数 */
/************/
int main()
{
/*
	 代入
*/
	std::cout << std::endl;
	std::cout << "代入\n";
					// newを使用しない場合
	std::cout << std::endl;
	std::cout << "   newを使用しない場合\n";
	Complex c1(1, 2), c2(3, 4);
	Vector1 v1(1, 0.0, 0.0), v2(2, -1.0, -2.0);
						// 代入前
	std::cout << std::endl;
	std::cout << "      c1(代入前) " << c1.r << " " << c1.i << std::endl;
	std::cout << "      c2(代入前) " << c2.r << " " << c2.i << std::endl;
	std::cout << "      v1(代入前) " << v1.n << " " << v1.x[0] << " " << v1.x[1] << std::endl;
	std::cout << "      v2(代入前) " << v2.n << " " << v2.x[0] << " " << v2.x[1] << std::endl;
						// 代入
	c1 = c2;
	v1 = v2;
						// 代入後
	std::cout << std::endl;
	std::cout << "      c1(c2をc1に代入後) " << c1.r << " " << c1.i << std::endl;
	std::cout << "      c2(c2をc1に代入後) " << c2.r << " " << c2.i << std::endl;
	std::cout << "      v1(v2をv1に代入後) " << v1.n << " " << v1.x[0] << " " << v1.x[1] << std::endl;
	std::cout << "      v2(v2をv1に代入後) " << v2.n << " " << v2.x[0] << " " << v2.x[1] << std::endl;
						// 値の変更
	c2.r = -1.5;
	v2.x[0] = 1.5;
						// 変更後の値
	std::cout << std::endl;
	std::cout << "      c1(c2.rを-1.5に変更後) " << c1.r << " " << c1.i << std::endl;
	std::cout << "      c2(c2.rを-1.5に変更後) " << c2.r << " " << c2.i << std::endl;
	std::cout << "      v1(v2.x[0]を1.5に変更後) " << v1.n << " " << v1.x[0] << " " << v1.x[1] << std::endl;
	std::cout << "      v2(v2.x[0]を1.5に変更後) " << v2.n << " " << v2.x[0] << " " << v2.x[1] << std::endl;
					// newを使用する場合
	std::cout << std::endl;
	std::cout << "   newを使用する場合\n";
	Vector2 v3(3, 0.0, 0.0), v4(4, -1.0, -2.0);
						// 代入前
	std::cout << std::endl;
	std::cout << "      v3(代入前) " << v3.n << " " << v3.x[0] << " " << v3.x[1] << std::endl;
	std::cout << "      v4(代入前) " << v4.n << " " << v4.x[0] << " " << v4.x[1] << std::endl;
						// 代入
	v3 = v4;
						// 代入後
	std::cout << std::endl;
	std::cout << "      v3(v4をv3に代入後) " << v3.n << " " << v3.x[0] << " " << v3.x[1] << std::endl;
	std::cout << "      v4(v4をv3に代入後) " << v4.n << " " << v4.x[0] << " " << v4.x[1] << std::endl;
						// 値の変更
	v4.n    = 5;
	v4.x[0] = 1.5;
						// 変更後の値(v3.x[0]も変化してしまう)
						// (デストラクタが定義されていると実行時にエラー)
	std::cout << std::endl;
	std::cout << "      v3(v4.nを5,v4.x[0]を1.5に変更後) " << v3.n << " " << v3.x[0] << " " << v3.x[1] << std::endl;
	std::cout << "      v4(v4.nを5,v4.x[0]を1.5に変更後) " << v4.n << " " << v4.x[0] << " " << v4.x[1] << std::endl;
/*
	 初期化
*/
	std::cout << std::endl;
	std::cout << "初期化\n";
					// newを使用しない場合
	std::cout << std::endl;
	std::cout << "   newを使用しない場合\n";
	Complex c4(3, 4);
	Complex c3 = c4;
	Vector1 v6(2, -1.0, -2.0);
	Vector1 v5 = v6;
					// 変更前
	std::cout << std::endl;
	std::cout << "      c3(変更前) " << c3.r << " " << c3.i << std::endl;
	std::cout << "      c4(変更前) " << c4.r << " " << c4.i << std::endl;
	std::cout << "      v5(変更前) " << v5.n << " " << v5.x[0] << " " << v5.x[1] << std::endl;
	std::cout << "      v6(変更前) " << v6.n << " " << v6.x[0] << " " << v6.x[1] << std::endl;
					// 値の変更
	c4.r    = -1.5;
	v6.x[0] = 1.5;
					// 変更後の値
	std::cout << std::endl;
	std::cout << "      c3(c4.rを-1.5に変更後) " << c3.r << " " << c3.i << std::endl;
	std::cout << "      c4(c4.rを-1.5に変更後) " << c4.r << " " << c4.i << std::endl;
	std::cout << "      v5(v6.x[0]を1.5に変更後) " << v5.n << " " << v5.x[0] << " " << v5.x[1] << std::endl;
	std::cout << "      v6(v6.x[0]を1.5に変更後) " << v6.n << " " << v6.x[0] << " " << v6.x[1] << std::endl;
				// newを使用する場合
	std::cout << std::endl;
	std::cout << "   newを使用する場合\n";
	Vector2 v8(4, -1.0, -2.0);
	Vector2 v7 = v8;
					// 変更前
	std::cout << std::endl;
	std::cout << "      v7(変更前) " << v7.n << " " << v7.x[0] << " " << v7.x[1] << std::endl;
	std::cout << "      v8(変更前) " << v8.n << " " << v8.x[0] << " " << v8.x[1] << std::endl;
					// 値の変更
	v8.n    = 5;
	v8.x[0] = 1.5;
					// 変更後の値(v7.x[0]も変化してしまう)
					// (デストラクタが定義されていると実行時にエラー)
	std::cout << std::endl;
	std::cout << "      v7(v8.nを5,v8.x[0]を1.5に変更後) " << v7.n << " " << v7.x[0] << " " << v7.x[1] << std::endl;
	std::cout << "      v8(v8.nを5,v8.x[0]を1.5に変更後) " << v8.n << " " << v8.x[0] << " " << v8.x[1] << std::endl;

	return 0;
}
		
  このプログラムを実行すると,以下のような結果が得られます.
	代入
	
	   newを使用しない場合
	
	      c1(代入前) 1 2
	      c2(代入前) 3 4
	      v1(代入前) 1 0 0
	      v2(代入前) 2 -1 -2
	
	      c1(c2をc1に代入後) 3 4
	      c2(c2をc1に代入後) 3 4
	      v1(v2をv1に代入後) 2 -1 -2
	      v2(v2をv1に代入後) 2 -1 -2
	
	      c1(c2.rを-1.5に変更後) 3 4
	      c2(c2.rを-1.5に変更後) -1.5 4
	      v1(v2.x[0]を1.5に変更後) 2 -1 -2
	      v2(v2.x[0]を1.5に変更後) 2 1.5 -2
	
	   newを使用する場合
	
	      v3(代入前) 3 0 0
	      v4(代入前) 4 -1 -2
	
	      v3(v4をv3に代入後) 4 -1 -2
	      v4(v4をv3に代入後) 4 -1 -2
	
	      v3(v4.nを5,v4.x[0]を1.5に変更後) 4 1.5 -2
	      v4(v4.nを5,v4.x[0]を1.5に変更後) 5 1.5 -2
	
	初期化
	
	   newを使用しない場合
	
	      c3(変更前) 3 4
	      c4(変更前) 3 4
	      v5(変更前) 2 -1 -2
	      v6(変更前) 2 -1 -2
	
	      c3(c4.rを-1.5に変更後) 3 4
	      c4(c4.rを-1.5に変更後) -1.5 4
	      v5(v6.x[0]を1.5に変更後) 2 -1 -2
	      v6(v6.x[0]を1.5に変更後) 2 1.5 -2
	
	   newを使用する場合
	
	      v7(変更前) 4 -1 -2
	      v8(変更前) 4 -1 -2
	
	      v7(v8.nを5,v8.x[0]を1.5に変更後) 4 1.5 -2
	      v8(v8.nを5,v8.x[0]を1.5に変更後) 5 1.5 -2
			

(プログラム例 12.2 ) 代入と初期化の解決( = のオーバーロード) 

/****************************/
/* 代入と初期化             */
/*      coded by Y.Suganuma */
/****************************/
#include <iostream>

/***********************/
/* クラスComplexの定義 */
/***********************/
class Complex {
	public:
		double r, i;
		Complex (double r1, double i1)	 // コンストラクタ
		{
			r = r1;
			i = i1;
		}
};

/***********************/
/* クラスVector1の定義 */
/***********************/
class Vector1 {
	public:
		int n;
		double x[2];
		Vector1 (int n1, double x1, double x2)	 // コンストラクタ
		{
			n    = n1;
			x[0] = x1;
			x[1] = x2;
		}
};

/***********************/
/* クラスVector2の定義 */
/***********************/
class Vector2 {
	public:
		int n;
		double *x;
		Vector2 (int n1, double x1, double x2)	 // コンストラクタ
		{
			n    = n1;
			x    = new double [2];
			x[0] = x1;
			x[1] = x2;
		}
		Vector2 (const Vector2 &b)   // 初期化のためのコンストラクタ
		{
			x    = new double [2];      // メモリの確保
			n    = b.n;                 // 値の代入
			x[0] = b.x[0];
			x[1] = b.x[1];
		}
		~Vector2 () {delete [] x;}   // デストラクタ
		Vector2& Vector2::operator= (const Vector2 &);   // =のオーバーロード
};

/*******************************/
/* =のオーバーロード          */
/*      a = b (a.operator=(b)) */
/*******************************/
Vector2& Vector2::operator= (const Vector2 &b)
{
	if (&b == this)                 // 自分自身への代入を防ぐ
		return *this;
	else {
		delete [] x;                // 代入する前のメモリを解放
		x    = new double [2];      // メモリの確保
		n    = b.n;                 // 値の代入
		x[0] = b.x[0];
		x[1] = b.x[1];
		return *this;
	}
}

/************/
/* main関数 */
/************/
int main()
{
/*
	 代入
*/
	std::cout << std::endl;
	std::cout << "代入\n";
					// newを使用しない場合
	std::cout << std::endl;
	std::cout << "   newを使用しない場合\n";
	Complex c1(1, 2), c2(3, 4);
	Vector1 v1(1, 0.0, 0.0), v2(2, -1.0, -2.0);
						// 代入前
	std::cout << std::endl;
	std::cout << "      c1(代入前) " << c1.r << " " << c1.i << std::endl;
	std::cout << "      c2(代入前) " << c2.r << " " << c2.i << std::endl;
	std::cout << "      v1(代入前) " << v1.n << " " << v1.x[0] << " " << v1.x[1] << std::endl;
	std::cout << "      v2(代入前) " << v2.n << " " << v2.x[0] << " " << v2.x[1] << std::endl;
						// 代入
	c1 = c2;
	v1 = v2;
						// 代入後
	std::cout << std::endl;
	std::cout << "      c1(c2をc1に代入後) " << c1.r << " " << c1.i << std::endl;
	std::cout << "      c2(c2をc1に代入後) " << c2.r << " " << c2.i << std::endl;
	std::cout << "      v1(v2をv1に代入後) " << v1.n << " " << v1.x[0] << " " << v1.x[1] << std::endl;
	std::cout << "      v2(v2をv1に代入後) " << v2.n << " " << v2.x[0] << " " << v2.x[1] << std::endl;
						// 値の変更
	c2.r = -1.5;
	v2.x[0] = 1.5;
						// 変更後の値
	std::cout << std::endl;
	std::cout << "      c1(c2.rを-1.5に変更後) " << c1.r << " " << c1.i << std::endl;
	std::cout << "      c2(c2.rを-1.5に変更後) " << c2.r << " " << c2.i << std::endl;
	std::cout << "      v1(v2.x[0]を1.5に変更後) " << v1.n << " " << v1.x[0] << " " << v1.x[1] << std::endl;
	std::cout << "      v2(v2.x[0]を1.5に変更後) " << v2.n << " " << v2.x[0] << " " << v2.x[1] << std::endl;
					// newを使用する場合
	std::cout << std::endl;
	std::cout << "   newを使用する場合\n";
	Vector2 v3(3, 0.0, 0.0), v4(4, -1.0, -2.0);
						// 代入前
	std::cout << std::endl;
	std::cout << "      v3(代入前) " << v3.n << " " << v3.x[0] << " " << v3.x[1] << std::endl;
	std::cout << "      v4(代入前) " << v4.n << " " << v4.x[0] << " " << v4.x[1] << std::endl;
						// 代入
	v3 = v4;
						// 代入後
	std::cout << std::endl;
	std::cout << "      v3(v4をv3に代入後) " << v3.n << " " << v3.x[0] << " " << v3.x[1] << std::endl;
	std::cout << "      v4(v4をv3に代入後) " << v4.n << " " << v4.x[0] << " " << v4.x[1] << std::endl;
						// 値の変更
	v4.n    = 5;
	v4.x[0] = 1.5;
						// 変更後の値
	std::cout << std::endl;
	std::cout << "      v3(v4.nを5,v4.x[0]を1.5に変更後) " << v3.n << " " << v3.x[0] << " " << v3.x[1] << std::endl;
	std::cout << "      v4(v4.nを5,v4.x[0]を1.5に変更後) " << v4.n << " " << v4.x[0] << " " << v4.x[1] << std::endl;
/*
	 初期化
*/
	std::cout << std::endl;
	std::cout << "初期化\n";
					// newを使用しない場合
	std::cout << std::endl;
	std::cout << "   newを使用しない場合\n";
	Complex c4(3, 4);
	Complex c3 = c4;
	Vector1 v6(2, -1.0, -2.0);
	Vector1 v5 = v6;
						// 変更前
	std::cout << std::endl;
	std::cout << "      c3(変更前) " << c3.r << " " << c3.i << std::endl;
	std::cout << "      c4(変更前) " << c4.r << " " << c4.i << std::endl;
	std::cout << "      v5(変更前) " << v5.n << " " << v5.x[0] << " " << v5.x[1] << std::endl;
	std::cout << "      v6(変更前) " << v6.n << " " << v6.x[0] << " " << v6.x[1] << std::endl;
						// 値の変更
	c4.r    = -1.5;
	v6.x[0] = 1.5;
					// 変更後の値
	std::cout << std::endl;
	std::cout << "      c3(c4.rを-1.5に変更後) " << c3.r << " " << c3.i << std::endl;
	std::cout << "      c4(c4.rを-1.5に変更後) " << c4.r << " " << c4.i << std::endl;
	std::cout << "      v5(v6.x[0]を1.5に変更後) " << v5.n << " " << v5.x[0] << " " << v5.x[1] << std::endl;
	std::cout << "      v6(v6.x[0]を1.5に変更後) " << v6.n << " " << v6.x[0] << " " << v6.x[1] << std::endl;
				// newを使用する場合
	std::cout << std::endl;
	std::cout << "   newを使用する場合\n";
	Vector2 v8(4, -1.0, -2.0);
	Vector2 v7 = v8;
					// 変更前
	std::cout << std::endl;
	std::cout << "      v7(変更前) " << v7.n << " " << v7.x[0] << " " << v7.x[1] << std::endl;
	std::cout << "      v8(変更前) " << v8.n << " " << v8.x[0] << " " << v8.x[1] << std::endl;
					// 値の変更
	v8.n    = 5;
	v8.x[0] = 1.5;
					// 変更後の値
	std::cout << std::endl;
	std::cout << "      v7(v8.nを5,v8.x[0]を1.5に変更後) " << v7.n << " " << v7.x[0] << " " << v7.x[1] << std::endl;
	std::cout << "      v8(v8.nを5,v8.x[0]を1.5に変更後) " << v8.n << " " << v8.x[0] << " " << v8.x[1] << std::endl;

	return 0;
}
		
  このプログラムを実行すると,以下のような結果が得られます.
	代入
	
	   newを使用しない場合
	
	      c1(代入前) 1 2
	      c2(代入前) 3 4
	      v1(代入前) 1 0 0
	      v2(代入前) 2 -1 -2
	
	      c1(c2をc1に代入後) 3 4
	      c2(c2をc1に代入後) 3 4
	      v1(v2をv1に代入後) 2 -1 -2
	      v2(v2をv1に代入後) 2 -1 -2
	
	      c1(c2.rを-1.5に変更後) 3 4
	      c2(c2.rを-1.5に変更後) -1.5 4
	      v1(v2.x[0]を1.5に変更後) 2 -1 -2
	      v2(v2.x[0]を1.5に変更後) 2 1.5 -2
	
	   newを使用する場合
	
	      v3(代入前) 3 0 0
	      v4(代入前) 4 -1 -2
	
	      v3(v4をv3に代入後) 4 -1 -2
	      v4(v4をv3に代入後) 4 -1 -2
	
	      v3(v4.nを5,v4.x[0]を1.5に変更後) 4 -1 -2
	      v4(v4.nを5,v4.x[0]を1.5に変更後) 5 1.5 -2
	
	初期化
	
	   newを使用しない場合
	
	      c3(変更前) 3 4
	      c4(変更前) 3 4
	      v5(変更前) 2 -1 -2
	      v6(変更前) 2 -1 -2
	
	      c3(c4.rを-1.5に変更後) 3 4
	      c4(c4.rを-1.5に変更後) -1.5 4
	      v5(v6.x[0]を1.5に変更後) 2 -1 -2
	      v6(v6.x[0]を1.5に変更後) 2 1.5 -2
	
	   newを使用する場合
	
	      v7(変更前) 4 -1 -2
	      v8(変更前) 4 -1 -2
	
	      v7(v8.nを5,v8.x[0]を1.5に変更後) 4 -1 -2
	      v8(v8.nを5,v8.x[0]を1.5に変更後) 5 1.5 -2
			

(プログラム例 12.3 ) 行列の乗算 

  この例では,n 行 m 列行列と m 行 l 列行列( n,m,l は任意)の乗算を,演算子のオーバーロード機能を利用して実現しています.その際,初期化や代入の問題も考慮しています.

/****************************/
/* 行列の乗算               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>

/**********************/
/* クラスMatrixの定義 */
/**********************/
class Matrix {       /* 2次元行列 */
		int n;              // 行の数
		int m;              // 列の数
		double **mat;       // 行列本体
	public:
		Matrix(int, int);   // コンストラクタ(引数あり)
		Matrix(const Matrix &);   // 初期化のためのコンストラクタ
		Matrix() {n = 0;}   // コンストラクタ(引数無し)
		~Matrix()
		{
			if (n > 0) {
				for (int i1 = 0; i1 < n; i1++)
					delete [] mat[i1];
				delete [] mat;
			}
		}
		void input();       // 入力
		void output();      // 出力
		Matrix& operator= (const Matrix &);   // =のオーバーロード
	friend Matrix operator* (const Matrix &, const Matrix &);   // *のオーバーロード
};

/******************************/
/* コンストラクタ(引数あり) */
/******************************/
Matrix::Matrix(int n1, int m1)
{
	n    = n1;
	m    = m1;
	mat  = new double * [n];
	for (int i1 = 0; i1 < n; i1++)
		mat[i1] = new double [m];
}

/********************************/
/* 初期化のためのコンストラクタ */
/********************************/
Matrix::Matrix(const Matrix &A)
{
	n   = A.n;
	m   = A.m;
	mat = new double * [n];
	for (int i1 = 0; i1 < n; i1++) {
		mat[i1] = new double [m];
		for (int i2 = 0; i2 < m; i2++)
			mat[i1][i2] = A.mat[i1][i2];
	}
}

/********/
/* 入力 */
/********/
void Matrix::input()
{
	for (int i1 = 0; i1 < n; i1++) {
		printf("%d行目のデータ\n", i1+1);
		for (int i2 = 0; i2 < m; i2++) {
			printf("   %d列目の値は?", i2+1);
			scanf("%lf", &mat[i1][i2]);
		}
	}
}

/********/
/* 出力 */
/********/
void Matrix::output()
{
	for (int i1 = 0; i1 < n; i1++) {
		for (int i2 = 0; i2 < m; i2++)
			printf("%f ", mat[i1][i2]);
		printf("\n");
	}
}

/**********************/
/* *のオーバーロード */
/**********************/
Matrix operator* (const Matrix &A, const Matrix &B)
{
	Matrix C;
	if (A.m != B.n) {
		printf("***error  invalid data\n");
		exit(1);
	}
	else {
		C = Matrix(A.n, B.m);
		for (int i1 = 0; i1 < A.n; i1++) {
			for (int i2 = 0; i2 < B.m; i2++) {
				C.mat[i1][i2] = 0.0;
				for (int i3 = 0; i3 < A.m; i3++)
					C.mat[i1][i2] += A.mat[i1][i3] * B.mat[i3][i2];
			}
		}
	}
	return C;
}

/*******************************/
/* =のオーバーロード          */
/*      a = b (a.operator=(b)) */
/*******************************/
Matrix& Matrix::operator= (const Matrix &B)
{
	if (&B != this) {   // 自分自身への代入を防ぐ
		if (n > 0) {   // 代入する前のメモリを解放
			for (int i1 = 0; i1 < n; i1++)
				delete [] mat[i1];
			delete [] mat;
		}
		n   = B.n;
		m   = B.m;
		mat = new double * [n];   // メモリの確保と代入
		for (int i1 = 0; i1 < n; i1++) {
			mat[i1] = new double [m];
			for (int i2 = 0; i2 < m; i2++)
				mat[i1][i2] = B.mat[i1][i2];
		}
	}
	return *this;
}

/************/
/* main関数 */
/************/
int main()
{
	int n, m, l;

	printf("行列Aの行と列の数は? ");
	scanf("%d %d", &n, &m);
	printf("行列Bの列の数は? ");
	scanf("%d", &l);

	Matrix A(n, m);
	Matrix B(m, l);
	Matrix C;

	printf("行列A\n");
	A.input();
	printf("行列B\n");
	B.input();

	C = A * B;

	C.output();

	return 0;
}
		
  このプログラムを実行すると,以下に示すような結果が得られます.
行列Aの行と列の数は? 3 2
行列Bの列の数は? 2
行列A
1行目のデータ
   1列目の値は?1
   2列目の値は?2
2行目のデータ
   1列目の値は?3
   2列目の値は?4
3行目のデータ
   1列目の値は?5
   2列目の値は?6
行列B
1行目のデータ
   1列目の値は?1
   2列目の値は?0
2行目のデータ
   1列目の値は?0
   2列目の値は?1
1.000000 2.000000
3.000000 4.000000
5.000000 6.000000
		

静岡理工科大学 菅沼ホーム 全体目次 演習解答例 付録 索引