ポインタ変数を参照渡し


c++ ポインタ変数 参照渡し、と検索しても、
単にポインタ変数を引数にとっている関数の説明か、
ポインタ渡しと、参照渡しの違いについて、しか出てこない。。。
（検索の仕方が悪いかもしれないけど）

C++なら、ポインタ渡しとは別に、参照渡しができるから、
ポインタ変数自体も、参照渡しで関数に渡せば、
呼び出し元も、関数側も、形を変えずに処理できる、
と思ったので、やってみた。

以下試した処理とソースコード。

argvの内容を確認し、myargvに必要なメモリ領域を確保し、
argvの内容をコピーして、その内容を表示する。
表示後、確保したメモリ領域を解放する。

この処理を、指定した回数ループ処理する。
コピーした内容の表示は、ループ処理の１回目のみ行う。

最後にプロセスが使用した、最大メモリ使用量を表示する。

ループの回数を変更しても、メモリ使用量が増えないことを確認する。

```cpp:a.test

#include <cstdio>
#include <cstring>
#include <cstdlib>

#include <sys/time.h>
#include <sys/resource.h>

void print_resource() {
    struct rusage usage;
    getrusage(RUSAGE_SELF, &usage);

    std::printf("maxrss=%ld KB\n", usage.ru_maxrss);
}

void delete_arg(int &myargc, char** &myargv) {
    if (myargc == 0 || myargv == nullptr) {
        return;
    }

    for (int i = 0; i < myargc; ++i) {
        delete [] myargv[i];
    }

    delete [] myargv;

    myargc = 0;
    myargv = nullptr;
}

void arg_copy(int argc, char** argv, int &myargc, char** &myargv) {
    myargc = 0;
    myargv = nullptr;

    myargv = new char* [argc];

    for (int i = 0; i < argc; ++i, ++myargc) {
        size_t len = std::strlen(argv[i]);
        myargv[i] = new char[len + 1];
        std::strcpy(myargv[i], argv[i]);
    }
}

int main(int argc, char** argv) {
    if (argc < 2) {
        return 1;
    }

    int loop_count = std::atoi(argv[1]);

    int myargc;
    char** myargv;

    for (int i = 0; i < loop_count; ++i) {
        arg_copy(argc, argv, myargc, myargv);

        for (int index = 0; index < myargc; ++index) {
            if (i == 0) {
                std::printf("%s\n", myargv[index]);
            }
        }

        delete_arg(myargc, myargv);
    }

    print_resource();

    return 0;
}

```

動かしてみると、ちゃんと期待する動作をしている。
ループ回数が増えても、メモリ使用量が増大することはなく、
ちゃんと確保、解放を繰り返している。

<pre>
[root@localhost ~]# g++ --version
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[root@localhost ~]#
[root@localhost ~]# g++ --std=c++11 ./a.cpp
[root@localhost ~]# ./a.out 1 -c /tmp/test.config -o /tmp/out.txt
./a.out
1
-c
/tmp/test.config
-o
/tmp/out.txt
maxrss=828 KB
[root@localhost ~]# ./a.out 10 -c /tmp/test.config -o /tmp/out.txt
./a.out
10
-c
/tmp/test.config
-o
/tmp/out.txt
maxrss=824 KB
[root@localhost ~]# ./a.out 100 -c /tmp/test.config -o /tmp/out.txt
./a.out
100
-c
/tmp/test.config
-o
/tmp/out.txt
maxrss=828 KB
[root@localhost ~]# ./a.out 1000 -c /tmp/test.config -o /tmp/out.txt
./a.out
1000
-c
/tmp/test.config
-o
/tmp/out.txt
maxrss=824 KB
[root@localhost ~]# ./a.out 10000 -c /tmp/test.config -o /tmp/out.txt
./a.out
10000
-c
/tmp/test.config
-o
/tmp/out.txt
maxrss=824 KB
[root@localhost ~]#
</pre>


ちなみに、
void arg_copy(int argc, char** argv, int &myargc, char** &myargv)
を
void arg_copy(int argc, char** argv, int &myargc, char** myargv)
にすると、もれなくセグメンテーション違反で死ぬ。

もしchar** &myargvではなく、ポインタ変数で頑張るなら、
void arg_copy(int &argc, char** argv, int &myargc, char*** myargv)
にして、呼び出すとき
arg_copy(argc, argv, myargc, &myargv);
にする。

そして、arg_copy内部で、char** myargv_を別に用意して、もろもろ確保した後、
最後に、*myargv = myargv_、というように確保した領域のポインタをコピーする、
というなんだか面倒なことをする必要がある。

もしくは、関数の戻り値として、確保した領域のポインタを返す、とか。



ひとまず、ポインタ変数も、あまり気にせず、参照渡しできた、という話でした。