Winows XP と VS2005 Standard です。
以下のコードで、ビルドは(構造体に関して警告なしで)成功して実行できます。
しかし、 GetBoy(1).name, GetBoy(1).age=99;
などの Abeno Gorou に関する入力が出来ていないようで、空白、0 で表示されま
す。その他は意図したとおりの出力があり問題ありません。
なぜなのか教えてください。お願いします。 ちなみに、
BC++B 6でも同じようなことが起こります。
#include stdafx.h
#include <iostream>
using namespace std;
//----------------------------------
struct Boy
{
char name[22];
int age;
char adr[33];
int phone;
}boy[9], Rob;
//-------------------------
Boy GetBoy(int index)
{
return boy[index];
}
//--------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
strcpy(boy[0].name, Ozawa Sabrou);
boy[0].age=99;
strcpy(boy[0].adr, 6-77 Hanayashiki);
boy[0].phone=550088;
cout << naem= << boy[0].name << endl;
cout << age= << boy[0].age << endl;
cout << adr= << boy[0].adr << endl;
cout << phone= << boy[0].phone << endl;
cout << //----------------------------- << endl;
cout << naem= << GetBoy(0).name << endl;
cout << age= << GetBoy(0).age << endl;
cout << adr= << GetBoy(0).adr << endl;
cout << phone= << GetBoy(0).phone << endl;
cout << //----------------------------- << endl;
strcpy(GetBoy(1).name, Abeno Gorou);
GetBoy(1).age=99;
strcpy(GetBoy(1).adr, 6-77 Hanayashiki);
GetBoy(1).phone=220077;
cout << naem= << boy[1].name << endl;
cout << age= << boy[1].age << endl;
cout << adr= << boy[1].adr << endl;
cout << phone= << boy[1].phone << endl;
cout << //----------------------------- << endl;
cout << naem= << GetBoy(1).name << endl;
cout << age= << GetBoy(1).age << endl;
cout << adr= << GetBoy(1).adr << endl;
cout << phone= << GetBoy(1).phone << endl;
cout << //----------------------------- << endl;
strcpy(Rob.name, Wada Kennta);
Rob.age=99;
strcpy(Rob.adr, 6-77 Hanayashiki);
Rob.phone=470099;
cout << naem= << Rob.name << endl;
cout << age= << Rob.age << endl;
cout << adr= << Rob.adr << endl;
cout << phone= << Rob.phone << endl;
cout << //----------------------------- << endl;
cout << naem= << Rob.name << endl;
cout << age= << Rob.age << endl;
cout << adr= << Rob.adr << endl;
cout << phone= << Rob.phone << endl;
cout << //----------------------------- << endl;
return 0;
}
GetBoy(indx)が返しているのはboy[indx]のコピー.
Boy &GetBoy(indx)
等にすれば良いように見えます.
ウサギさん高速、8分後の回答ありがとうございました。
Boy & GetBoy(int index) で、できました。このときは本物を指し、
Boy GetBoy(int index) ではコピーを指しているというわけですね。
コピーなので本物とは別の(私には)わからないところにある(存在している)という
うことなんでしょうね。
でも関数内で宣言した変数を返しているわけではないので、本物を返してくれてもよい
と思うのですが・・・。
それなら、これもコピーを指すのかなと試してみると、
Boy GetBoyV(void)
{
return Rob;
}
入力、出力ができたのでこれは本物を指していることがわかりました。
どんな時に本物を指し、どんな時にコピーを指すのでしょうか?
まだ、判別ができません。C/C++の本に書いてあるでしょうか?
まだ納得できないのですが・・・。 よろしくお願いします。
構造体だとややこしいので、
この話の場合、int型でも一緒なので、int型にてサンプルです。
これで伝わるかな?
int nTest = 0;
int Test_Copy()
{
return nTest;
}
int& Test_Reference()
{
return nTest;
}
int _tmain(int argc, _TCHAR* argv[])
{
int nTest1 = Test_Copy(); // <- nTest1 == 0, nTest == 0
int& nTest2 = Test_Reference(); // <- nTest2 == 0, nTest == 0
nTest1 = 1; // <- nTest1 == 1, nTest == 0
nTest2 = 2; // <- nTest2 == 2, nTest == 2
Test_Reference() = 3; // <- nTest2 == 3, nTest == 3
}
bun さんサンプルありがとうございました。
頭を冷やして、実験をしながら、よく考えてみます。
わかったら、ここにご報告します。
> Boy GetBoyV(void)
> {
> return Rob;
> }
>
> 入力、出力ができたのでこれは本物を指していることがわかりました。
本当!?
strcpy(Rob.name, Wada Kennta);
Rob.age=99;
strcpy(Rob.adr, 6-77 Hanayashiki);
Rob.phone=470099;
cout << name= << Rob.name << endl;
cout << age= << Rob.age << endl;
cout << adr= << Rob.adr << endl;
cout << phone= << Rob.phone << endl;
cout << //----------------------------- << endl;
strcpy(GetBoyV().name, Kennta Wada);
Rob.age=99;
strcpy(GetBoyV().adr, Hanayashiki 6-77);
Rob.phone=470099;
cout << name= << Rob.name << endl;
cout << age= << Rob.age << endl;
cout << adr= << Rob.adr << endl;
cout << phone= << Rob.phone << endl;
cout << //----------------------------- << endl;
としてみましたが、前半と後半の出力は変わらず。
> でも関数内で宣言した変数を返しているわけではないので、本物を返してくれてもよい
> と思うのですが・・・。
>
> それなら、これもコピーを指すのかなと試してみると、
>
> Boy GetBoyV(void)
> {
> return Rob;
> }
>
> 入力、出力ができたのでこれは本物を指していることがわかりました。
>
> どんな時に本物を指し、どんな時にコピーを指すのでしょうか?
> まだ、判別ができません。C/C++の本に書いてあるでしょうか?
> まだ納得できないのですが・・・。 よろしくお願いします。
これは出来ないと思いますけれど。
念の為に簡単なソースでも確認してみましたが、
代入できていませんでした。
「本物を返してくれても良いと思う」という言葉が出てくると言う事は
多分、実体で返すと言う意味が分かっていない所為だと思います。
参照返しと実体返しの違いを良く考えて見た方が良いでしょう。
ををっ、書いている内に既に書き込みが。(^^;
実体返しというよりは複写返しといったほうがわかりやすいだろう・・・
良く考えたら実体返しではなくて値返しと言うべきですね。
参照返しの対にするであれば。
maru さん、PATIO さんありがとうございます。
「参照返し」と「実体返し」の違いに絞って考えたり、調べてみたりしてみます。
これをまちがえているようじゃ、とても危ないので!
> でも関数内で宣言した変数を返しているわけではないので、
> 本物を返してくれてもよいと思うのですが・・・。
本物を返す為には参照返ししかないのではと思ったり。
値を設定するという行為を行う為には元のインスタンスを
指し示す必要が有りますけれど、値返しの場合は、インスタンスが
抱える値を返却するわけなのでインスタンスその物が返る訳では
無いわけですよね。
で、元のインスタンスを指し示す目的は参照で達成できるわけなので
値返しで元のインスタンスを指し示せるわけが無いと。
私が参照とコピー渡しの違いを説明するときによく使う手です。
参照渡しは同一メモリ領域に対する別名(エイリアス)なんですね。
コピー渡しは、別メモリ領域を確保し、値だけをコピーします。
以下のようなコードに対して
---------------------------------------------------------
void Test(int& nTest1, nTest2)
{
int& nTest3 = nTest1;
int nTest4 = nTest2;
}
int _tmain(int argc, _TCHAR* argv[])
{
int nMain = 0;
Test(nMain, nMain);
}
---------------------------------------------------------
メモリ上にどういう風にそれぞれの変数がロードされるかというと、
テキストだけで書こうとするとつらいのですが、以下のような感じです。
横方向がメモリ番地。
同じ列の変数は同一メモリ領域を共有しています。
メモリ番地 →
--------------------------------------------------
| _tmain():nMain | Test():nTest2 | Test():nTest4 |
| Test():nTest1 | | |
| Test():nTest3 | | |
--------------------------------------------------
void Test(int& nTest1, nTest2)
↓
void Test(int& nTest1, int nTest2)