オブジェクトを返す関数

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
C++わからへん

オブジェクトを返す関数

#1

投稿記事 by C++わからへん » 5年前

#include "stdafx.h"
#include <iostream>
#include <cstdlib>
using namespace std;

class myclass {
int *p, x;
public:
myclass(int i, int n = 0);
myclass(const myclass &o, int n = 0);
~myclass() { delete p; }
friend int getval(myclass o);
friend int f1(myclass o);
myclass f2();
};

myclass::myclass(int i, int n)
{
cout << "通常のコンストラクタ呼び出し\n";

p = new int;

if (!p) {
cout << "メモリ割り当てエラー\n";
exit(1);
}
*p = i;

x = n;
}

myclass::myclass(const myclass &o, int n)
{
cout << "コピーコンストラクタ呼び出し\n";

p = new int;

if (!p) {
cout << "メモリ割り当てエラー\n";
exit(1);
}
*p = *o.p;

x = n;
}

int getval(myclass o)
{
return *o.p;
}

int f1(myclass o)
{
cout << "オブジェクトを受け取る\n";

return o.x;
}

myclass myclass::f2()
{
cout << "オブジェクトを返す\n";

myclass c(3);
return c;
}

int main()
{
myclass a(1), b(2);

cout << getval(a) << " " << getval(b);
cout << "\n";
cout << f1(a) << " " << f1(b);
cout << "\n";

a = a.f2();
b = b.f2();

cout << getval(a) << " " << getval(b);
cout << "\n";
cout << f1(a) << " " << f1(b);
cout << "\n";

return 0;
}

上のプログラムでオブジェクトを返す関数f2でa,bにcを代入して、getvalで3を表示したいのですが、実行するとマイナスがついた大きな数字が表示されます。代入する前のgetvalは1 2と正しく表示されます。どこをどう直すべきでしょうか。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: オブジェクトを返す関数

#2

投稿記事 by みけCAT » 5年前

myclassクラスの代入演算子がオーバーロードされていないため、

コード:

a = a.f2();
b = b.f2();
の部分でポインタの値がコピーされ、
寿命が尽きることによりまだ使う領域が開放されてしまいます。
ポインタの値ではなく、領域の内容をコピーするような代入演算子の定義をmyclassに追加するといいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: オブジェクトを返す関数

#3

投稿記事 by かずま » 5年前

フォーラム(掲示板)ルールに従って、コードタグを使用してください。

new int は NULL を返しません。
std::bad_allocクラスのオブジェクトを throw します。
exit() は使わず、try catch を使うべきでしょう。

getval や f1 の引数は const myclass& にしたほうが、無駄な
コンストラクタやデストラクタを使用しなくて効率が良いでしょう。

代入演算子を定義してみました。

コード:

#include <iostream>
using namespace std;

class myclass {
	int *p, x;
public:
	 myclass(int i, int n = 0);
	 myclass(const myclass& o, int n = 0);
	~myclass() { delete p; }
	friend int getval(const myclass& o);
	friend int f1(const myclass& o);
	myclass f2();
	myclass& operator=(const myclass& o);
};

myclass::myclass(int i, int n)
{
	cout << "通常のコンストラクタ呼び出し\n";
	p = new int;
	*p = i;
	x = n;
}

myclass::myclass(const myclass & o, int n)
{
	cout << "コピーコンストラクタ呼び出し\n";
	p = new int;
	*p = *o.p;
	x = n;
}

myclass& myclass::operator=(const myclass& o)
{
	if (&o != this) {
		delete p;
		p = new int;
		*p = *o.p;
		x = o.x;
	}
	return *this;
}

int getval(const myclass& o) { return *o.p; }

int f1(const myclass& o)
{
	cout << "オブジェクトを受け取る\n";
	return o.x;
}

myclass myclass::f2()
{
	cout << "オブジェクトを返す\n";
	return myclass(3);  // return 3; でもよい
}

int main()
{
	try {
		myclass a(1), b(2);

		cout << getval(a) << " " << getval(b) << endl;
		cout << f1(a) << " " << f1(b) << endl;

		a = a.f2();
		b = b.f2();

		cout << getval(a) << " " << getval(b) << endl;
		cout << f1(a) << " " << f1(b) << endl;
	}
	catch (bad_alloc& e) {
		cout << "メモリ割り当てエラー\n";
		// cout << e.what() << endl;
		return 1;
	}
	return 0;
}

かずま

Re: オブジェクトを返す関数

#4

投稿記事 by かずま » 5年前

この myclass の場合、代入演算子の定義の中の
delete p; p = new int; は不要でしょう。

クラスによっては、例えば std::vector などのクラスでは、

コード:

	vector<int> a = { 1, 2, 3 }, b = { 4, 5, 6, 7, 8 };
	a = b;
size() の異なる代入では、内部でポインタの delete と new が必要です。

返信

“C言語何でも質問掲示板” へ戻る