C++ 参照渡しの勉強 ① 値渡し

　別項でROS2の勉強をしている。最初はコピペで何とかやってきたが、そうもいかなくなってきた。ちゃんとC++のプログラミングを学ぶときがやってきた。とはいえ、ROS2の勉強自体がとん挫しているので、いい機会だと思い、構造体の勉強を集中的にすることにした。
 
### なぜ参照渡しが使われるのかを知る前に
　C言語では、
- 値渡し　　　　``int nibai( int a )``
- ポインタ渡し　``bool nibai( int* a )``

の二つの方法があって、入門書では値渡しが事例で用いられてきました。これは、関数を呼び出したとき、値がコピーされるので、メモリを消費します。そして、回収しないと、メモリア領域は減少していく？　百万回実行したら大変です。きっと。
　ただ、関数を抜けるときに使ったメモリはOS？に戻される仕様らしいので、メモリ・リークはない模様です。


　ポインタ渡しは、呼び出し元の**変数のアドレス**を引数として関数に渡します。関数は引数として渡された**アドレスが格納されたポインタ変数**を使って呼び出し、元の変数にアクセスし、値に対して何らかの変更を行います。呼び出した後、値は変更されているので、それをmain側では使います。
 　という説明をよく見ますが、よくわからないです。この勉強で、結果的に理解でき、応用ができけばと思っています。


- 参照渡し　　　``void nibai( int& a )``

　参照渡しはC++で追加されたそうです。なぜかということも調べなくては。

### 環境
- Raspberry Pi 5 8GB
- 追加ボード；NVMe Base for Raspberry Pi 5 (NVMe Base by Pimoroni)
- Crucial クルーシャル P2シリーズ 500GB 3D NAND NVMe PCIe M.2 SSD CT500P2SSD8
- Ubuntu Desktop 24.04LTS(64-bit)

 Windows10で、検索窓にcmdと入れ、コマンドプロンプトを起動します。
　sshでログインします。
```
C:\Users\yoshi>ssh yoshi.local
```

### 値渡しでGo
　worksディレクトリで作業をします。

##### 基本のビルド

```
$ mkdir works
$ cd works
$ nano works0.cpp
```
　最初のテスト・プログラムです。

```works0.cpp
#include <iostream>

int main(){
    std::cout << "HelloWorld." << std::endl;
    return 0;
}
```
　Cmakeを使ってビルドしてみます。
```
$ nano CMakeLists.txt
```

```CMakeLists.txt
cmake_minimum_required(VERSION 3.8)

project(worksFirst)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

add_executable(main works0.cpp)
```
　cmakeで実行プログラムをビルドします。
```
$ cmake -S . -B build
$ cd build
$ make
$ ./main
HelloWorld.
```

##### 関数化を試す
　関数readTempData()は、文字列を実数に変換するという内容です。
 
```
nano works1.cpp
```

```works1.cpp
#include <iostream>
#include <string>

auto readTempData(std::string todayTemp){
    return stof(todayTemp)/1000.0;
}

int  main(){
    std::string todayTemp ="37600";

    std::cout << "今日の気温" <<  readTempData(todayTemp) << "`C" << std::endl;
    return 0;
}
```
　Cmakeは使わず、コンパイルしてみます。

```
$ g++ works1.cpp -o auto
$ ./auto
今日の気温37.6`C
```

### CPUの温度を取得して表示
　少し具体的なプログラムで試します。

```works2.cpp
#include <iostream>
#include <string>
#include <fstream>

auto readTempData(std::string cpuTemp){
    return stof(cpuTemp)/1000.0;
}

int  main(){
    std::ifstream ifs("/sys/class/thermal/thermal_zone0/temp");
    std::string cpuTemp;

    if (ifs.fail()) {
        std::cerr << "Failed to open file." << std::endl;
        return -1;
    }
    getline(ifs, cpuTemp);
    std::cout << "\n read CPU temp " << cpuTemp << std::endl;

    std::cout << "CPUの温度" <<  readTempData(cpuTemp) << "`C" << std::endl;
    return 0;
}
```
　コンパイルし、実行します。
```
$ g++ works2.cpp -o auto
$ ./auto

 read CPU temp 46300
CPUの温度46.3`C
```

### 構造体を扱う

　``/proc/stat``は、各CPUコア別の情報とトータル（4コア）の処理時間情報が別々に出力されます。
```
$ cat /proc/stat
cpu  41031 1023 25330 49592707 8299 0 21 0 0 0
cpu0 10826 383 7172 12395623 2017 0 19 0 0 0
cpu1 10402 389 6800 12398373 1769 0 0 0 0 0
cpu2 10107 85 5881 12398458 2557 0 1 0 0 0
cpu3 9694 165 5476 12400251 1954 0 0 0 0 0
intr 17599378 0 41218 3408976 0 0 0 2179822 0 0 0 0 0 0 8134083 129352 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 302 2 0 3009 0 886 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 297542 0 111 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 0 0 0 0 1319 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3272093 0 23096 21704 26263 21645 20336 7 0 0 10591 0 0 5 5 0 0 0 0 0 0 0 0 6948 0
ctxt 19942565
btime 1723991367
processes 8768
procs_running 1
procs_blocked 0
softirq 7697426 1426 2342022 5 295036 5410 0 637 3000634 0 2052256
```
　1行目だけに注目します。CPUタイムとして、最初の4項目のうち、niceを除いて取り扱います。プログラミングの都合でそうしただけです。
- user：ユーザ・モードで費やされた時間
- nice：ユーザ・モードで低優先度（nice）で過ごした時間
- system：システム・モードで費やされた時間
- idle：アイドル・タスクで費やされた時間
 
　これを構造体で構成します。構造体は、いくつかの変数をひとまとめにします。``main``の中で、
 ```
 cpuInfo info = {"","",""};
 ```
 と記述したのは、構造体を一つの変数``info``でハンドリングできるためです。構造体の中のそれぞれの変数はメンバと呼ばれ、
 ```
    info.User = user;
    info.System = system;
    info.Idle = idle;
```
のように、個別に代入ができます。
　構造体の宣言部分です。
 
 ```
struct cpuInfo {
    std::string User;
    std::string System;
    std::string Idle;
};
 ```

 ##### 構造体を引数にとる関数
 　構造体を関数の引数として渡す、ここでは値渡しになると思います。

```C++
float  hiritsu(struct cpuInfo info){
    std::cout << "\n in subroutine hiritsu " << std::endl;
    float total = stof(info.User) + stof(info.System) + stof(info.Idle);
    std::cout << "\n total " << total << std::endl;

    return 0;
}
```
　構造体``struct cpuInfo``は、データ型の名前で、引数``info``を受け取って計算する関数``hiritsu()``という説明であっているのかな。
 　三つのinfo変数のメンバを足し算して表示しているだけの内容です。計算結果を戻してはいません。

　``main``からは、
 ```
 hiritsu(info);
 ```
 変数を引数に呼び出しています。
 

```works3.cpp
#include <iostream>
#include <string>
#include <fstream>

struct cpuInfo {
    std::string User;
    std::string System;
    std::string Idle;
};

float hiritsu(cpuInfo data);

int  main(){

    std::ifstream ifs("/proc/stat");
    cpuInfo info = {"","",""};
    std::string firstCpuData;

    if (ifs.fail()) {
        std::cerr << "Failed to open file." << std::endl;
        return -1;
    }
    getline(ifs, firstCpuData);
    std::cout << firstCpuData << std::endl;

    firstCpuData = firstCpuData.substr(5);
    std::string user = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(user.size()+1);

    std::string nice = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(nice.size()+1);

    std::string system = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(system.size()+1);

    std::string idle = firstCpuData.substr(0,firstCpuData.find(" "));
    firstCpuData = firstCpuData.substr(idle.size()+1);

    info.User = user;
    info.System = system;
    info.Idle = idle;

    std::cout << "user:" << info.User << std::endl;
    std::cout << "system:" << info.System << std::endl;
    std::cout << "idle:" << info.Idle << std::endl;

    hiritsu(info);


    ifs.close();
    return 0;
}

float  hiritsu(struct cpuInfo info){
    std::cout << "\n in subroutine hiritsu " << std::endl;
    float total = stof(info.User) + stof(info.System) + stof(info.Idle);
    std::cout << "\n total " << total << std::endl;

    return 0;
}
```
　実行しました。
```
$ g++ works3.cpp -o auto
$ ./auto
cpu  40940 1023 25249 49418771 8290 0 21 0 0 0
user:40940
system:25249
idle:49418771

 in subroutine hiritsu

 total 4.9485e+07
 ```

 　mainで、構造体のメンバに、読み取ったCPUタイムを書き込みました。
  hiritsu関数に、その構造体を値渡しし、三つのメンバを加算して表示しました。
  　という内容なので、何も破綻するところはないです。きっと。
  　値渡しの問題点は、呼び出した関数の中で構造体のメンバを変更し、mainに戻ったときに、変更内容が反映されていないという、**問題点**があるということらしいです。それは不便だ！みたいな。
   　でも、なぜか、こういう事例がいっぱい見つかります。
  　次回確認します。

### 勉強 勉強　そして勉強
　嫌いな言葉だな。

　関数の前に、floatと書いたけど、よくある事例をコピペしただけど、意味合いがわかっていない。
 　物は試し、``int``に変えた。
```
$ g++ works4s.cpp -o auto
yoshi@yoshi:~/works$ ./auto
user:123
system:234
idle:345

-in subroutine getCpuInfoData-
cpu  101677 4485 70862 140934880 13459 0 51 0 0 0

user:101677
system:70862
idle:140934880

total  1.41107e+08
user %   0.0720564
system % 0.0502185
idle %   99.8777
```
　問題なくコンパイルできるし、動く。

　まず、mainの前に書いた
```
float hiritsu(cpuInfo data);

int  main(){
```
だけど、これは何？？　昔プロトタイピングと言って、コンパイラに、後ろのほうに実際の関数の記述があるということを知らせている役目だ、というのを学んだ記憶がある。そもそもmainの前に、関数を書いてしまえば、不要なものだとも。
　調べました。
 　間違っていました。**プロトタイプ**が正しいです。正確には、関数プロトタイプというようです。
  で、型だけど、何のためかというと、関数の戻り値の型のようで、今回は、
```
  return 0;
```  
　コピペばっかりやっているので、｝閉じるのまえに書き入れただけで、役目がわかっていない。
 　普通、関数の戻り値が'0'であれば、正常終了という解釈をするの？もし、'-1'とかだったらエラーありで、'43'とかの数値だったら、関数のエラー・メッセージを探して何のエラーだったかを解析できる、という話？
  であれば、今回の関数は、表示をするだけなので、returnを返さないというのも文法的にはあり？試してみました。
  関数の型をvoidにしましたが、コンパイラに怒られました。そうです、関数内で、ファイルを読み出したとき、``return -1``という処理を入れていたのですね。
  ということで、元のintに戻しました。

 ------

 https://qiita.com/jamjam/items/d9dfb1819b8ca513ac03

https://qiita.com/jamjam/items/cca4f181397daeac1ac2

https://qiita.com/jamjam/items/e7a734f85f4554ba6273

https://qiita.com/jamjam/items/28cb7fcd678b39378090  
  
https://qiita.com/jamjam/items/6c0b48747fd405989917