Java が値渡しなのか値渡しなのかについて、インターネットで長い間検索した結果、この問題について合理的な説明がインターネット上にないことがわかりました。この問題は正しい説明です。
この質問は言語レベルの設計に関係するので、すべての構造をボトムアップでリストします。この構造の合理性は自明です。
アセンブリ言語における即値と直接アドレス指定について
即値は、通常、即値アドレッシング モード命令で指定された数値を参照します。
ムーブ イークス、 33221100H
このアセンブリ言語については、33221100H を汎用レジスタ EAX に直接入れることであり、必要な手順は 1 つだけです。
(AX のフルネームは Accumulator Register、アキュムレーション レジスタ、E はエクステンド、つまり 32 ビットに拡張することを意味します)
MOV 命令は、ソース オペランドをデスティネーション オペランドにコピーします)。
ダイレクト・アドレッシングとは、命令フォーマットのアドレス・フィールドで、メモリ内のオペランドのアドレスを直接指し示すことです。
MOV EAX, [0x04]
このアセンブリ ステートメントは、メモリ 0x04 の値を抽出し、それを汎用レジスタ EAX に入れることです. 0x04 に従ってこのメモリを見つけ、このメモリの値を取得して EAX レジスタに入れる必要があります.
即値が消費するCPUクロックサイクルは直接アドレッシングよりも少なく、即値はより高速であることがわかります
C++ の文字列メモリ レイアウトについて
メモリ内の文字列の格納は状況によって異なるため、この質問が C++ 文字列から始まるのはなぜですか?
22文字未満を格納する場合
22文字以上を格納する場合
格納される文字列の長さ (sizeof ではなく strlen) が 22 以下の場合、関数スタックに直接格納され、最後のバイト (最上位アドレス) に文字列の実際の長さが格納されます。
格納される文字列の長さが 22 を超える場合、追加のヒープ メモリ領域が文字列自体を格納するために割り当てられ、スタック内の24 バイト領域は他の目的に使用されます。24 バイトの先頭 8 バイト;
中央の 8 バイトには文字列の長さが格納されます;
最後の 8 バイト: 最上位アドレスのバイトは 0x80 に固定され、残りのバイトには割り当てられたヒープ領域のサイズが格納されます
文字数が 22 バイト未満の場合、目的のコンテンツがすぐに見つかることがわかります。
22バイト以上の場合、アドレスジャンプが必要となり、上記より速度が遅くなります
この時点で、アセンブリ言語の例を挙げた理由がわかります
22 バイト未満の場合は即値に相当し、22 バイトを超える場合はアドレス指定が必要です。
仮想マシンのメモリ レイアウトに
Java または C# 言語の仮想マシンで
基本型 byte、boolean、short、char int、float、long double は、123 などのスタック メモリに格納されます。
オブジェクトはヒープ メモリに配置され、ヒープの参照 (またはポインター) である 1 レベルのインデックスのみがスタックに配置されます。
スタックとヒープの深い理解
コンピュータの最下層、特にハードウェア構造
CPUには、ヒープよりも高速なスタックを操作するための特別なスタックポインターレジスターとベースアドレスポインターレジスター(esp、ebp)があります
スタックを実際にディレクトリとして機能させ、ヒープをコンテンツとして機能させます.ヒープ上のコンテンツには2次ジャンプが必要です.
基本型など容量の少ないものは直接スタックに積む
そして容量の大きいものはヒープにのせます。
さらに、C++ はスタックにメモリを割り当てることができます。以前の記事を参照してください。
C++ で 3 種類の new を使用する方法を詳しく説明する (new を使用してスタック上にオブジェクトを生成する) - Programmer Sought
Javaは値による値または値による参照です
2 つの例として Java を直接取り上げます
最初の例
int A = 123;
int B = A;
この時点で、出力 B はまだ 123 です。
2番目の例
classT A = new classT;
classT B = A;
Java の文字列は本質的にクラスであるため、この例は文字列にも機能します。
この時点で、B によって出力された classT は、同じ空間を指しているため、まだ A です。
つまり、値はスタックで渡され、参照はヒープで渡されます。