静的局所変数から見たC,C++,C#,Java,PHPの特徴
3319 ワード
0問題の由来
この問題に対する思考は,オブジェクト向け設計における単例設計モデルの実現から来ている.
C++における一例モード実現標準コードは以下の通りである.
インスタンス関数GetTheOnly()の取得では、静的ローカル変数ユーザは一意のインスタンスを格納し、初期化時にinit()関数を使用して動的に初期化します.
このように簡単に見えますが、同じコードをCとしてコンパイルすることはできません.コンパイラはstatic int x=init()をコンパイルする行でエラーが発生しました.
エラー:初期値設定要素が定数ではありません
C言語の静的ローカル変数は、初期化時に定数で値を割り当てる必要があります.つまり、この初期値はコンパイル中に決定される必要があります.
よく考えてみると、関数を呼び出して静的変数を初期化し、C++はinit()を保証しなければならない.一度だけ実行します.この目的を達成するために、C++コンパイラは追加コードを追加しなければなりません.私が考えることができるC++コンパイラはstatic int x=init()です.追加可能な疑似コードは次のとおりです.
さらに他のいくつかの言語のこの問題に対する処理を見たいと思って、その後C#、Java、PHPを使って類似の実験を行って、小さい結論を得ました.
1 C#,Javaでは静的ローカル変数はまったくサポートされていません
両方は静的メンバー変数のみをサポートし、関数内の静的ローカル変数はサポートしません.考えてみれば、静的ローカル変数は、ほとんど常に静的メンバー変数を使用して置き換えることができます.
C#テストコード:
Javaテストコード:
2 PHPは静的局所変数に対してCと同じであり、定数初期化のみをサポートする
PHPテストコード:
3少し考える
静的局所変数という非常に小さな言語の詳細によって,これらの言語の特徴を発見することができる.
C++コンパイラは勤勉で全面的な全才で、できるだけユーザーにもっと多くの言語機能を提供して、これらをこっそりユーザーのためにコードを生成しなければならなくて、それによってC++言語の複雑さと“氷山効果”を招きます.△C++の多重継承、スタック上のオブジェクト、複製構造を考えてみましょう...
JavaとC#は使いやすさを重視し、二義性を避け、同じ機能に対して、ユーザーに正しい選択を与えるだけだ.(単一継承、対象はスタックにしか建てられず、ゴミ回収を考えてみましょう)
Cは常に簡潔で効率的で透明であり,コンパイラは老いぼれており,コードを見ても生成されたアセンブリを基本的に予測できる.
PHPの構造化部分はCの文法を模倣しているため、多くの特性が似ているが、それはあくまでも解釈言語であり、特に変数名、クラス名など自体が変数の解釈言語特性として機能し、異常に柔軟になる.オブジェクト向け部分はJavaの文法を模倣するとともに,解釈言語の特徴を十分に体現している.
この問題に対する思考は,オブジェクト向け設計における単例設計モデルの実現から来ている.
C++における一例モード実現標準コードは以下の通りである.
#include <stdio.h>
int init()
{
printf("init()
");
return 22;
}
int GetTheOnly()
{
static int x = init();
return x;
}
int main()
{
int only = GetTheOnly();
return 0;
}
インスタンス関数GetTheOnly()の取得では、静的ローカル変数ユーザは一意のインスタンスを格納し、初期化時にinit()関数を使用して動的に初期化します.
このように簡単に見えますが、同じコードをCとしてコンパイルすることはできません.コンパイラはstatic int x=init()をコンパイルする行でエラーが発生しました.
エラー:初期値設定要素が定数ではありません
C言語の静的ローカル変数は、初期化時に定数で値を割り当てる必要があります.つまり、この初期値はコンパイル中に決定される必要があります.
よく考えてみると、関数を呼び出して静的変数を初期化し、C++はinit()を保証しなければならない.一度だけ実行します.この目的を達成するために、C++コンパイラは追加コードを追加しなければなりません.私が考えることができるC++コンパイラはstatic int x=init()です.追加可能な疑似コードは次のとおりです.
static int x;
static char flag = 0;
if(flag == 0){
x = init();
flag = 1;
}
return x;
では、C++コンパイラがプライベートで余分なアセンブリコードを生成していることがわかります.その結果、C++は使いやすいが、理解しにくいという結果になった.さらに他のいくつかの言語のこの問題に対する処理を見たいと思って、その後C#、Java、PHPを使って類似の実験を行って、小さい結論を得ました.
1 C#,Javaでは静的ローカル変数はまったくサポートされていません
両方は静的メンバー変数のみをサポートし、関数内の静的ローカル変数はサポートしません.考えてみれば、静的ローカル変数は、ほとんど常に静的メンバー変数を使用して置き換えることができます.
C#テストコード:
using System;
namespace ConsoleApplication2
{
class Program
{
static int x = 0;
static int init()
{
Console.WriteLine("init()");
return 22;
}
static int GetTheOnly()
{
// static int x = 0; static local variable is NOT supported by C#.
if(x == 0)
{
x = init();
}
return x;
}
static void Main(string[] args)
{
GetTheOnly();
GetTheOnly();
}
}
}
Javaテストコード:
public class t{
public static int init(){
System.out.println("init()
");
return 22;
}
private static int x = 0;
public static int getTheOnly(){
//static int x = 0; This line cannot be compiled, static local variable is NOT supported by Java
if(x==0){
x = init();
}
return x;
}
public static void main(String[] args) {
getTheOnly();
getTheOnly();
}
}
2 PHPは静的局所変数に対してCと同じであり、定数初期化のみをサポートする
PHPテストコード:
<?php
function init()
{
echo "init()
";
return 22;
}
function getTheOnly()
{
// static $x = init(); PHP only supports initializing static local vairalbel with constant.
static $x = 0;
if($x==0){
$x = init();
}
return $x;
}
getTheOnly();
getTheOnly();
3少し考える
静的局所変数という非常に小さな言語の詳細によって,これらの言語の特徴を発見することができる.
C++コンパイラは勤勉で全面的な全才で、できるだけユーザーにもっと多くの言語機能を提供して、これらをこっそりユーザーのためにコードを生成しなければならなくて、それによってC++言語の複雑さと“氷山効果”を招きます.△C++の多重継承、スタック上のオブジェクト、複製構造を考えてみましょう...
JavaとC#は使いやすさを重視し、二義性を避け、同じ機能に対して、ユーザーに正しい選択を与えるだけだ.(単一継承、対象はスタックにしか建てられず、ゴミ回収を考えてみましょう)
Cは常に簡潔で効率的で透明であり,コンパイラは老いぼれており,コードを見ても生成されたアセンブリを基本的に予測できる.
PHPの構造化部分はCの文法を模倣しているため、多くの特性が似ているが、それはあくまでも解釈言語であり、特に変数名、クラス名など自体が変数の解釈言語特性として機能し、異常に柔軟になる.オブジェクト向け部分はJavaの文法を模倣するとともに,解釈言語の特徴を十分に体現している.