0 問題の起源
この問題についての考えは、オブジェクト指向設計におけるシングルトン設計パターンの実装に由来しています。
C++ でシングルトン モードを実装するための標準コードは次のとおりです:
#include <stdio.h>int init(){ printf("init()\n"); return 22;}int GetTheOnly(){ static int x = init(); return x;}int main(){ int only = GetTheOnly(); return 0;}
とてもシンプルに見えますが、同じコードを C としてコンパイルすることはできません static int x = init() 行をコンパイルすると、コンパイラはエラーを報告します:
エラー: 初期化子要素は定数ではありません
It C 言語の静的ローカル変数には、初期化時に定数値を割り当てる必要があることがわかります。これは、初期値がコンパイラーによって決定される必要があることを意味します。
関数を呼び出して静的変数を初期化するには、C++ が init(); を 1 回だけ実行するようにする必要があります。この目的を達成するには、C++ コンパイラは、static int x = init(); に対して考えられる追加のコードを追加する必要があります。コンパイラが密かに冗長なアセンブリコードを生成しました。その結果、C++ は使いやすいですが、理解するのは簡単ではありません。
1 C# と Java は静的ローカル変数をまったくサポートしません
どちらも静的メンバー変数のみをサポートし、関数内の静的ローカル変数はサポートしません。考えてみれば当然のことですが、静的ローカル変数はほとんどの場合、静的メンバー変数に置き換えることができます。C# テスト コード:
static int x; static char flag = 0; if(flag == 0){ x = init();Java テスト コード:
flag = 1; } return x;2 PHP は静的ローカル変数を C と同じように扱い、定数の初期化のみをサポートします
りー
3時'時計思考C++ コンパイラーは、ユーザーにより多くの言語機能を提供しようとする、勤勉で包括的な万能ツールです。ただし、これを行うには、ユーザーのためにコードを秘密裏に生成する必要があり、これが C++ 言語と「氷山効果」。 (C++ の多重継承、スタック上のオブジェクト、コピー構造を考えてください...)
Java と C# は使いやすさに重点を置き、曖昧さを避け、同じ関数に対してユーザーに正しい選択肢を 1 つだけ提供します。 (単一継承、オブジェクトはヒープ上でのみ作成可能、ガベージ コレクションについて考えてください)
C は常にその単純さ、効率性、透明性を維持しており、コンパイラーは正直で誠実であり、基本的にいつ生成されるアセンブリを予測できます。コードが表示されます。
PHP の構造部分は C の構文を模倣しているため、多くの機能が C に似ていますが、結局はインタープリター言語であり、特に変数名やクラス名などはそれ自体がインタープリター言語として使用できます。変数の特徴を利用できるため、信じられないほど柔軟になります。オブジェクト指向部分は Java の構文を模倣しながら、インタプリタ型言語の特性を完全に体現しています。