说是改良,不过C++的死忠份子可能认为是对C++的亵渎,随便怎么说,就说是不一样的地方吧。
最近D语言没什么大动作,我又参与到xruby的builtin开发中,圈子里有点冷清。有留言说这里没什么人关注,的确是这样,抽点时间来写个简单的比较。
这里有一份各种语言的比较,大致可以了解D语言要对C++改些什么。
http://digitalmars.com/d/comparison.html
下面没什么顺序,想到什么就先列出来,可能随时扩充。
[b]1、内存管理。[/b]
内存管理在C++中非常难以掌握,大多数C++程序员没有写过内存管理程序,多数C++程序中存在内存问题,C++程序员终其一生都在与内存管理做斗争(有点过了。。)。
内存管理这么困难和重要,为何不彻底解决呢?垃圾收集是许多语言支持的一种内存管理方式,从语言级别上支持垃圾收集,你只需要分配,不需要释放。多数java程序员终其一生无法搞挂java虚拟机,对C++程序员来说把自己的程序搞挂是小儿科。
D语言也支持垃圾回收,不过为了照顾C++程序员对在堆栈上分配对象的喜好,它也支持这种方式。
[code]
import std.stdio;
class Test{
public:
this(){writefln("constructor");}
~this(){writefln("destructor");}
}
void main(){
writefln("start");
{
auto Test t = new Test; # LINE A
}
writefln("end");
}
[/code]
上面这段代码,在#LINE A处分配了一个Test对象,当退出它的作用域后,它的析构函数将被调用。注意这一行的auto关键字。
你也可以定义一个普通的对象,在退出作用域时调用delete来显示析构它。当然在复杂逻辑中,这个不太好控制,比如下面这段代码:
[code]
void foo(boolean flag){
Test t = new Test;
if (flag) return;
delete t;
}
[/code]
如果flag值为true,直接return了,可能与你的期望并不一致。D语言支持另一个关键字:
void foo(boolean flag){
Test t = new Test;
scope(exit) delete t;
if (flag) return;
}
scope(exit)声明了退出此作用域时要执行的代码,现在没有这个问题了,无论你后面有多少个可能return的分支。scope有更精细的控制,scope(success)和scope(failure)分别在正常退出作用域和出现异常时执行。
scope guard准确说是为了资源管理(RAII)而实现的,并不只是为了内存管理。对RAII的支持还可以使用auto关键字,把一个类声明为auto,就只能使用auto方式定义变量。
[b]2、委托。[/b]
委托也不是新东西,在脚本语言中应该是早就出现了吧,C#也支持委托。C++并不支持委托,仅仅从C那里借了个函数指针,稍稍做了点修改做成成员函数指针。不过这个东东并不好用,除了要面对怪异的语法以外,使用它也不方便。
委托的本质是一个对象指针和一个函数指针的绑定,为什么在C++中实现却如何艰难?原因就是C++支持的多继承,以及各种编译器实现上的差异,有兴趣的搜索一下“成员函数指针与高性能的C++委托”。
D语言分别实现了函数指针类型和委托类型,全局函数和声明为extern(C)的函数的指针就是这种类型;委托类型则是D对象的成员函数指针,注意是对象的不是类的,类方法取指针依旧是函数指针类型,因为它没有绑定对象;内嵌函数的指针也是委托类型。
D语言的委托是对象指针和函数指针的简单结合,你可以使用hack手段来增强它。(见这一篇: http://dlang.iteye.com/group/blog/26618 )
[b]3、单元测试[/b]
单元测试最好是写在实现代码附近,方便及时修改对照,D语言使用unittest关键字来支持它。
你可以在代码的任意位置使用unittest来标明单元测试代码,并使用assert来编写测试代码,在编译器命令行上加-unittest就可以编译出含有单元测试代码的程序。正式的应用可能不会这么简陋,要实现出单元测试类,捕获AssertError异常,否则每一个异常就中断了测试可没什么价值。
[b]4、契约编程[/b]
D语言的方法不仅有函数体,还可以加入2个附加的in和out代码块,这时原来的函数体要用body来标识:
[code]
int foo(int bar)
in{
assert(bar >= 0);
assert(bar <= 255);
}
out(result){
assert(result == 0);
}
body{
return bar % 2;
}
void main(){
foo(30);
foo(-2);
foo(256);
foo(31);
}
[/code]
代码应该不难看懂,in和out分别是分别标明前置条件(preconditions)检查和后置条件(postconditions)检查,还有一个不变量检查,只能用在结构、联合、类中:
[code]
import std.stdio;
class Foo{
private:
int value = 0;
invariant{
writefln("check");
assert(value == 0);
}
public:
void foo(){
writefln("in");
value = 1;
writefln("out");
}
}
void main(){
Foo foo = new Foo;
foo.foo();
}
[/code]
invariant会在每个public方法调用前后执行,输出如下:
[code]
check
in
out
check
Error: AssertError Failure tt(8)
[/code]
D目前不能打印出异常堆栈,提示信息有点差。
[b]5、同步原语[/b]
这在D语言里就是synchronized关键字:
[code]
import std.stdio;
import std.thread;
import std.c.time;
class PrintThread : Thread {
public:
int run(){
synchronized {
writefln("Thread start");
usleep(100000);
writefln("Thread end");
}
return 0;
}
}
void main(){
PrintThread[] threads = new PrintThread[10];
for (int i=0; i<10; ++i){
threads[i] = new PrintThread;
threads[i].start();
}
usleep(1100000);
}
[/code]
也可以synchronized(object),和java差不多。
6、COM接口兼容
通过使用extern(Windows)声明,D接口可以和COM接口二进制兼容。不多说了,看这篇: http://qiezi.iteye.com/admin/show/26681
-----------
先整这么多,有时间补充,毛糙了点,多多包涵。
最近D语言没什么大动作,我又参与到xruby的builtin开发中,圈子里有点冷清。有留言说这里没什么人关注,的确是这样,抽点时间来写个简单的比较。
这里有一份各种语言的比较,大致可以了解D语言要对C++改些什么。
http://digitalmars.com/d/comparison.html
下面没什么顺序,想到什么就先列出来,可能随时扩充。
[b]1、内存管理。[/b]
内存管理在C++中非常难以掌握,大多数C++程序员没有写过内存管理程序,多数C++程序中存在内存问题,C++程序员终其一生都在与内存管理做斗争(有点过了。。)。
内存管理这么困难和重要,为何不彻底解决呢?垃圾收集是许多语言支持的一种内存管理方式,从语言级别上支持垃圾收集,你只需要分配,不需要释放。多数java程序员终其一生无法搞挂java虚拟机,对C++程序员来说把自己的程序搞挂是小儿科。
D语言也支持垃圾回收,不过为了照顾C++程序员对在堆栈上分配对象的喜好,它也支持这种方式。
[code]
import std.stdio;
class Test{
public:
this(){writefln("constructor");}
~this(){writefln("destructor");}
}
void main(){
writefln("start");
{
auto Test t = new Test; # LINE A
}
writefln("end");
}
[/code]
上面这段代码,在#LINE A处分配了一个Test对象,当退出它的作用域后,它的析构函数将被调用。注意这一行的auto关键字。
你也可以定义一个普通的对象,在退出作用域时调用delete来显示析构它。当然在复杂逻辑中,这个不太好控制,比如下面这段代码:
[code]
void foo(boolean flag){
Test t = new Test;
if (flag) return;
delete t;
}
[/code]
如果flag值为true,直接return了,可能与你的期望并不一致。D语言支持另一个关键字:
void foo(boolean flag){
Test t = new Test;
scope(exit) delete t;
if (flag) return;
}
scope(exit)声明了退出此作用域时要执行的代码,现在没有这个问题了,无论你后面有多少个可能return的分支。scope有更精细的控制,scope(success)和scope(failure)分别在正常退出作用域和出现异常时执行。
scope guard准确说是为了资源管理(RAII)而实现的,并不只是为了内存管理。对RAII的支持还可以使用auto关键字,把一个类声明为auto,就只能使用auto方式定义变量。
[b]2、委托。[/b]
委托也不是新东西,在脚本语言中应该是早就出现了吧,C#也支持委托。C++并不支持委托,仅仅从C那里借了个函数指针,稍稍做了点修改做成成员函数指针。不过这个东东并不好用,除了要面对怪异的语法以外,使用它也不方便。
委托的本质是一个对象指针和一个函数指针的绑定,为什么在C++中实现却如何艰难?原因就是C++支持的多继承,以及各种编译器实现上的差异,有兴趣的搜索一下“成员函数指针与高性能的C++委托”。
D语言分别实现了函数指针类型和委托类型,全局函数和声明为extern(C)的函数的指针就是这种类型;委托类型则是D对象的成员函数指针,注意是对象的不是类的,类方法取指针依旧是函数指针类型,因为它没有绑定对象;内嵌函数的指针也是委托类型。
D语言的委托是对象指针和函数指针的简单结合,你可以使用hack手段来增强它。(见这一篇: http://dlang.iteye.com/group/blog/26618 )
[b]3、单元测试[/b]
单元测试最好是写在实现代码附近,方便及时修改对照,D语言使用unittest关键字来支持它。
你可以在代码的任意位置使用unittest来标明单元测试代码,并使用assert来编写测试代码,在编译器命令行上加-unittest就可以编译出含有单元测试代码的程序。正式的应用可能不会这么简陋,要实现出单元测试类,捕获AssertError异常,否则每一个异常就中断了测试可没什么价值。
[b]4、契约编程[/b]
D语言的方法不仅有函数体,还可以加入2个附加的in和out代码块,这时原来的函数体要用body来标识:
[code]
int foo(int bar)
in{
assert(bar >= 0);
assert(bar <= 255);
}
out(result){
assert(result == 0);
}
body{
return bar % 2;
}
void main(){
foo(30);
foo(-2);
foo(256);
foo(31);
}
[/code]
代码应该不难看懂,in和out分别是分别标明前置条件(preconditions)检查和后置条件(postconditions)检查,还有一个不变量检查,只能用在结构、联合、类中:
[code]
import std.stdio;
class Foo{
private:
int value = 0;
invariant{
writefln("check");
assert(value == 0);
}
public:
void foo(){
writefln("in");
value = 1;
writefln("out");
}
}
void main(){
Foo foo = new Foo;
foo.foo();
}
[/code]
invariant会在每个public方法调用前后执行,输出如下:
[code]
check
in
out
check
Error: AssertError Failure tt(8)
[/code]
D目前不能打印出异常堆栈,提示信息有点差。
[b]5、同步原语[/b]
这在D语言里就是synchronized关键字:
[code]
import std.stdio;
import std.thread;
import std.c.time;
class PrintThread : Thread {
public:
int run(){
synchronized {
writefln("Thread start");
usleep(100000);
writefln("Thread end");
}
return 0;
}
}
void main(){
PrintThread[] threads = new PrintThread[10];
for (int i=0; i<10; ++i){
threads[i] = new PrintThread;
threads[i].start();
}
usleep(1100000);
}
[/code]
也可以synchronized(object),和java差不多。
6、COM接口兼容
通过使用extern(Windows)声明,D接口可以和COM接口二进制兼容。不多说了,看这篇: http://qiezi.iteye.com/admin/show/26681
-----------
先整这么多,有时间补充,毛糙了点,多多包涵。