戻り値が呼び出し元に渡される方法も、関数呼び出し規則の一部です。ここを参照してください。
例えば、以下についてcdecl
:
cdecl
呼び出し規約は、x86 アーキテクチャの多くの C システムで使用されています。ではcdecl
、関数パラメータは右から左の順序でスタックにプッシュされます。関数の戻り値は EAX レジスタに返されます (x87 レジスタ ST0 に返される浮動小数点値を除く)。
[...]
cdecl
の解釈、特に値を返す方法にはいくつかのバリエーションがあります。その結果、異なるオペレーティング システム プラットフォーム用にコンパイルされた x86 プログラムや、異なるコンパイラによってコンパイルされた x86 プログラムは、両方がcdecl
慣習であり、基盤となる環境を呼び出さないでください。一部のコンパイラは、EAX:EDX で 2 レジスタ以下の長さの単純なデータ構造を返します。また、例外ハンドラ (定義済みのコンストラクタ、デストラクタ、または代入など) による特別な処理を必要とするより大きな構造とクラス オブジェクトは、メモリに返されます。「メモリ内」で渡すには、呼び出し元がメモリを割り当て、そのメモリへのポインタを非表示の最初のパラメータとして渡します。呼び出し先はメモリにデータを入力してポインターを返し、戻るときに非表示のポインターをポップします。
ヒープにメモリを割り当てる場合、スタック操作は必要なヒープ操作よりもはるかに高速になるため、スタックは常に高速です。(C で) ヒープ上の何かへのポインターを返したい唯一の理由は、それがスタックに収まらないからです。
説明:
上記の最後の文で、「あなたが望むかもしれない唯一の理由...」は、「通常、ポインターを返す理由はない」と解釈されるべきではありません。むしろ、「ポインターを返さずに必要なことを実行できる場合、とにかくポインターを使用することを決定する唯一の理由は...」ということです。
もちろん、クリスが彼自身の答えで述べているように、関数からポインターを返す正当な理由はたくさんありますが、そうする必要がない場合についてのみ話しています。
つまり、可能な場合は値で返します。必要な場合はポインタを使用してください。