構造体へ入力、エラーがないのに入力できない

[戻る]
EyeWash 2009/08/20(木) 09:14:23
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;
}
 

ホウジョウウサギ 2009/08/20(木) 09:22:04
GetBoy(indx)が返しているのはboy[indx]のコピー.
Boy &GetBoy(indx)
等にすれば良いように見えます.

EyeWash 2009/08/20(木) 10:30:41
ウサギさん高速、8分後の回答ありがとうございました。

Boy & GetBoy(int index) で、できました。このときは本物を指し、
Boy GetBoy(int index) ではコピーを指しているというわけですね。
コピーなので本物とは別の(私には)わからないところにある(存在している)という
うことなんでしょうね。

でも関数内で宣言した変数を返しているわけではないので、本物を返してくれてもよい
と思うのですが・・・。

それなら、これもコピーを指すのかなと試してみると、

Boy GetBoyV(void)
{
    return Rob;
}

入力、出力ができたのでこれは本物を指していることがわかりました。

どんな時に本物を指し、どんな時にコピーを指すのでしょうか?
まだ、判別ができません。C/C++の本に書いてあるでしょうか?
まだ納得できないのですが・・・。 よろしくお願いします。

bun 2009/08/20(木) 10:55:38
構造体だとややこしいので、
この話の場合、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
}

EyeWash 2009/08/20(木) 11:22:42
bun さんサンプルありがとうございました。
頭を冷やして、実験をしながら、よく考えてみます。
わかったら、ここにご報告します。

maru 2009/08/20(木) 11:54:11
> 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;
としてみましたが、前半と後半の出力は変わらず。

PATIO 2009/08/20(木) 12:15:50
> でも関数内で宣言した変数を返しているわけではないので、本物を返してくれてもよい
> と思うのですが・・・。
> 
> それなら、これもコピーを指すのかなと試してみると、
> 
> Boy GetBoyV(void)
> {
>     return Rob;
> }
> 
> 入力、出力ができたのでこれは本物を指していることがわかりました。
> 
> どんな時に本物を指し、どんな時にコピーを指すのでしょうか?
> まだ、判別ができません。C/C++の本に書いてあるでしょうか?
> まだ納得できないのですが・・・。 よろしくお願いします。

これは出来ないと思いますけれど。
念の為に簡単なソースでも確認してみましたが、
代入できていませんでした。

「本物を返してくれても良いと思う」という言葉が出てくると言う事は
多分、実体で返すと言う意味が分かっていない所為だと思います。
参照返しと実体返しの違いを良く考えて見た方が良いでしょう。

PATIO 2009/08/20(木) 12:17:44
ををっ、書いている内に既に書き込みが。(^^;

tetrapod 2009/08/20(木) 12:39:24
実体返しというよりは複写返しといったほうがわかりやすいだろう・・・

PATIO 2009/08/20(木) 13:05:54
良く考えたら実体返しではなくて値返しと言うべきですね。
参照返しの対にするであれば。

EyeWash 2009/08/20(木) 13:07:54
maru さん、PATIO さんありがとうございます。 
「参照返し」と「実体返し」の違いに絞って考えたり、調べてみたりしてみます。
これをまちがえているようじゃ、とても危ないので!

PATIO 2009/08/20(木) 13:10:29
> でも関数内で宣言した変数を返しているわけではないので、
> 本物を返してくれてもよいと思うのですが・・・。

本物を返す為には参照返ししかないのではと思ったり。

値を設定するという行為を行う為には元のインスタンスを
指し示す必要が有りますけれど、値返しの場合は、インスタンスが
抱える値を返却するわけなのでインスタンスその物が返る訳では
無いわけですよね。
で、元のインスタンスを指し示す目的は参照で達成できるわけなので
値返しで元のインスタンスを指し示せるわけが無いと。

bun 2009/08/20(木) 14:54:51
私が参照とコピー渡しの違いを説明するときによく使う手です。
参照渡しは同一メモリ領域に対する別名(エイリアス)なんですね。
コピー渡しは、別メモリ領域を確保し、値だけをコピーします。

以下のようなコードに対して

---------------------------------------------------------
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  |        |        |
--------------------------------------------------

bun 2009/08/20(木) 14:56:12
void Test(int& nTest1, nTest2)
  ↓
void Test(int& nTest1, int nTest2)

古いスレッドには追加発言できません。