アプリ版:「スタンプのみでお礼する」機能のリリースについて

オブジェクトの作成と関数との関係を勉強していますが参照の使い方に関して質問させていただきたいと思います。

以下のような簡単なプログラムを作りました。

myclass.cpp myclass.h で記述されたクラスmyclassは整数を一つ持ち、show_value関数でその整数を表示し、say_heyで"hey"という文字を出力するというものです。

このクラスを利用するプログラムとしてmain.cppをつくりました。このなかには2つの関数が使われます。
-オブジェクトをつくりそれをオブジェクトとして返す関数(return_obj)  
-オブジェクトをつくりそれの参照を返す関数(return_ref_obj)
これらの関数を用いてオブジェクトをつくり、そのオブジェクトを戻り値としてmainのなかでオブジェクトのshow_value関数で保持する整数を表示する、というものです。


myclass.h--------------------------------

class Myclass{

public:
int my_int;
Myclass();
~Myclass();
void show_value();
void say_hey();
};


myclass.cpp----------------------------------

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


Myclass::Myclass(){};

Myclass::~Myclass(){};

void Myclass::show_value(){
printf("%d\n", my_int);
}

void Myclass::say_hey(){
printf("hey\n");
}

main.cpp------------

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

//オブジェクトをつくりそれをオブジェクトとして返す関数(return_obj)  
Myclass return_obj(int int_in){

Myclass myobject;
myobject.my_int = int_in; //引数をオブジェクトのmy_intに渡す
return myobject;
}

//オブジェクトをつくりそれの参照を返す関数(return_ref_obj)
Myclass& return_ref_obj(int int_in2){

Myclass myobject;
myobject.my_int = int_in2;   //引数をオブジェクトのmy_intに渡す
Myclass& ref_of_myclass = myobject;
return ref_of_myclass;

}

void main(){

Myclass returned_obj = return_obj(1); //関数に1を渡し、1を保持するオブジェクトを作成
returned_obj.show_value(); //整数(1)表示
returned_obj.say_hey();

Myclass& ref_obj = return_ref_obj(2); //関数に2を渡し、2を保持するオブジェクトを作成し参照として受け取る
ref_obj.show_value(); //整数(2)表示
ref_obj.say_hey();

}


プログラムを実行した出力-------------------
1
hey
-858993460
hey


このようにオブジェクト自体を返してコピーしたもの(return_obj使用)はshow_valueでただしくオブジェクトに保持された数が表示されますが 参照でオブジェクトを返したもの(return_ref_obj使用)はアドレスのような数列が表示されます。

質問A
これはオブジェクトの参照を返す関数(return_ref_obj)でオブジェクトを作成しても、そのオブジェクトが関数の中でのみ実在しており、関数がおわるとその実体がなくなるためではないかと解釈しているのですがそれで正しいでしょうか?
質問B
関数でオブジェクトを作成してそれをプログラム本体に渡すときはreturn_objのようにオブジェクト自体をコピーしなければ参照などで渡すことはできないのでしょうか?

クラスと参照自体勉強を始めたばかりで色々と初歩的な間違いもあるとは思いますが、よろしくお願いします

A 回答 (2件)

rinkun さんがおっしゃるとおり、


「関数がおわるとその実体がなくなるため」
という理解で正しいです。

newしてポインタを返すほかには、関数内の自動変数を静的に宣言する方法があります。
シングルトンパターンになるんですかね。

こんな感じです。

class A& method()
{
  static class A;
  return A;
}

これなら、method() をreturnした後も class Aはなくならないので大丈夫なはずです。
また、呼び出し元でdeleteしなくても済みます。
ただし、複数の呼び出し元で、ひとつのインスタンスを共通して使用することになるので、その点は注意が必要です。

特に、起動後初回の呼び出しで class Aのコンストラクタが処理されるので、初回呼び出し時に複数スレッドから同時にアクセスされると例外が発生することがあります。
    • good
    • 0
この回答へのお礼

具体的なコードありがとうございます。勉強になりました。
new, staticなどは知識としては多少ありましたが、実際に使うのはちょっと躊躇してしまっていました。これからは積極的に使ってみようと思います。

お礼日時:2011/02/19 00:58

質問A:その理解で正しいです。


質問B:作ったオブジェクトを参照で返すのは止めた方が良いです。
オブジェクトをコピーで返しましょう。
あるいはnewで作ってポインタで返しましょう。

関数内で自動変数を宣言して作ったオブジェクトはその関数を終えると削除されるので、そこへの参照は懸垂参照という不正な状態になります。
newで作成したオブジェクトはdeleteするまで存在するので関数から返せます。このときは参照でなくポインタを返しましょう。参照を返すとdeleteが面倒です。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
ポインタはなにかと面倒そうなイメージもあり、参照が使えないかと思っていたんですがそうもいかないようですね。
今回のようなオブジェクトの有効な範囲というのは私がプログラミングでいまいち感覚がつかめていなかった部分なのですが、今回の件でとても勉強になりました。

お礼日時:2011/02/17 20:29

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!