通过静态局部变量看C,C++,C#,Java,PHP的特点

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;
}

在获取实例函数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()\n");
        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()\n";
    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的语法,同时又充分体现了解释语言的特点。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值