0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

見えるけど見えないもの。それは「メンバ関数の第一引数」さ

Last updated at Posted at 2022-06-11

結論

C++のメンバ関数の第一引数は、そのインスタンスのアドレスです。
static関数はメンバ変数を使用する必要がないため、例外です。

以下は解説と茶番です。

C++のメンバ関数をスレッド実行したかった

std::thread、_beginthread、CreateThreadと色々あるが、今日は気分でCreateThreadをチョイス。
image.png

書いてみたら何やらエラーが。エラー内容は以下

型 "DWORD (__stdcall hoge::*)(LPVOID pParam)" の引数は型 "LPTHREAD_START_ROUTINE" のパラメータと互換性がありません

「なるほど、スレッド化したい関数と型が違うとな。ちゃんと定義を確認しに行こう」

minwinbase.h
typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(
    LPVOID lpThreadParameter
    );
typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
戻り値 呼び出し規約 引数
DWORD WINAPI LPVOID一つ

「合っとるやんけ。何で使えないんや。」

メンバ変数の第一引数はインスタンスのアドレスなのです

論より証拠ということで、実際のソースコードと生成されたアセンブラを見てみましょう。

元のソースコード
int main()
{
	hoge instance;

	instance.hugaThread(NULL);

	return 0;
}
生成されたアセンブラ
	hoge instance;
00007FF7B6CA19AD  lea         rcx,[instance]  
00007FF7B6CA19B1  call        hoge::hoge (07FF7B6CA100Fh)  
00007FF7B6CA19B6  nop  

	instance.hugaThread(NULL);
00007FF7B6CA19B7  xor         edx,edx  
00007FF7B6CA19B9  lea         rcx,[instance]  
00007FF7B6CA19BD  call        hoge::hugaThread (07FF7B6CA137Fh)

Windows10 VisualStudio2022 x64でビルドしたものです。
このアセンブラから、以下の処理が確認できます。

  • instanceの宣言をしたところで、コンストラクタを呼び出している
  • edx(rdx)レジスタを0クリア、つまりNULLを格納している
  • instanceのアドレスをrcxレジスタに格納している

MSのx64環境では一般的に第一引数から順にrcx、rdx、r8、r9に格納されます。詳細はこちらを御覧ください。
x64 での呼び出し規則

よって、スレッド化しようとしたメンバ変数の方は本当は以下のようになっているのです。

DWORD WINAPI hoge::hugaThread(hoge* myself, PVOID pParam);

内部的にこうしてくれているおかげで、メンバ関数内で、インスタンスのメンバ変数にアクセスできているわけですね。
C言語では構造体を作って各関数に渡してステータスを変更/参照するといったことになりますが、内部的にはそれをやっているのと大して変わりはないわけです。

これの仕組みが理解できれば、冒頭で書いた通り、staticのメンバ関数であればCreateThreadに渡す事ができる理屈を察する事ができると思います。

C++のメンバ関数をスレッド実行する

本記事ではメインの話題ではありませんが、こういった所で躓く人もいらっしゃると思うので、他の方の記事のリンクを貼り付けておきます。

https://kakashibata.hatenablog.jp/entry/2019/09/29/210359
https://qiita.com/tsuru3/items/c3e706ed77912f809cd2
https://stackoverflow.com/questions/1372967/how-do-you-use-createthread-for-functions-which-are-class-members

おわり

以上、お読みいただきありがとうございました。
全然遊戯王ネタ入れるところなかった。

0
0
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?