|
在第一版设计中,是有GC的。这个版本试图设计一种无GC的语言。
起因是我给第一版设计上加了unique功能试图优化性能。但是发现GC是全局的,无论管理的多少内存,都需要扫描整个程序使用的所有内存。所以unique也起不到什么作用。unique实际上是0-1引用计数,为什么不直接使用引用计数代替GC呢。毕竟广义上说引用计数也是GC的一种。 设计的目标仍然是:做自动内存管理语言里面性能最好的。
指针种类
把指针分为如下几种:
int* p; //默认带引用计数的指针。
int& p; //临时指针,生命期只在当前函数内有效。
uniuqe int* p; //同时只有一个持有者的指针
weak int* p; //弱引用指针,为了解决循环引用问题
unsafe int* p; //不安全指针,需要手动释放内存。这里关键的地方是int&,不是引用,而是读作临时指针。
指针安全
编译时保证指针安全,不会出现悬垂指针问题。
本地变量取地址后是临时指针:
int a;
int& p = &a;引用计数指针能转换为临时指针。为了防止指针失效,临时指针可由编译器生成一个隐藏指针来持有。例如:
int* p;
int& t = p;
p = null;编译器生成如下代码:
int* p;
int* _t = p;
int& t = _t;
p = null;临时指针不可转为其他指针:
int& t = ..
int* p = t; //compile error;函数参数尽量使用临时指针,避免引用计数开销:
void foo(int &t) {
...
}
int* p = ...;
foo(p);衍生指针只能是临时指针,而且这里编译器也要增加隐藏变量来保持父对象引用:
struct A {
int x;
int y;
}
A* a = ...
int& p = &a.y;拷贝
值语义的拷贝赋值需要维护引用计数。但这由编译器内部负责,并不开放给外部。
struct A {
int* i;
}
A a;
A b = a; //拷贝的时候自动维护i的引用计数。性能预期
如果说第一版有GC版对标Go语言,那么这次就是对标swift了。
性能优势:
1.能灵活的选择栈上分配内存。
2.内存能嵌入其他结构体内部。
3.有unique指针来提高性能。
4.隐式转临时指针,避免引用计数开销。
有这4点性能上比swift肯定高出很多。要是再用一下unsafe指针,性能和C一致。
<hr/>后面的内容和第一版基本相同,可以不用看。
<hr/>继承与多态
我觉得继承和多态是语言抽象能力的重要体现。并且这种抽象没有性能开销。如果信了组合优于继承的话,可以不用这个特性,不是强制的。
和Java一样的单类多接口继承。只有标记为virtual的结构才能有虚方法。
interface I {
virtual void foo() { ... }
}
virtual struct B {
int a;
virtual void bar() { ... }
}
struct A : B, I {
B* b;
override void foo(B* b) {
...
}
override void bar() {...}
}没有构造函数和析构函数。
指针使用
指针使用点语法调用方法,而不用->
A a;
A* b;
a.foo();
b.foo();指针类型转换。
A *a = cast<A*>(p);
B *a = unsafe_cast<B*>(p);指针默认不允许运算,可临时转为数组处理。
数组
数组定义和C一致,但是传参数时变成一种自带长度的胖指针。数组在运行时检查越界。
int[14] a;
foo(int[] a) {
print(a.length);
print(a[0]);
}
foo(a);数组和指针相互转换
int *p;
int[] a = as_array(p, 5);
int *q = a.pointer;异常
众所周知C++中没人使用异常。并不是异常不好,而是异常和手动内存管理不兼容。所有可能抛出异常的函数必须使用throws关键字标记。
void foo() throws {
}
void dar() throws {
foo();
}
void bar2() {
try {
foo();
}
catch (Exception *e) {
}
}模板泛型
使用了C++类似的模板来支持泛型。
struct Bar<T> {
void foo(): T {
...
}
}null
指针默认不能为null,除非后面有问号
B* a;
B*? a = null;getter/setter
使用操作符重载的方式来定义getter/setter。
struct Bar {
private int _size;
setter void size(int s) {
this._size = s;
}
}
Bar b;
b.size = 2; // call b.size(2);去掉的特性
并不是特性越多越好,去掉很多C++的特性。
- 不支持引用,只有指针。
- 没有class,只有struct。
- 没有头文件
- 不支持函数通过参数重载
- 不支持一次定义多个变量。
- 不支持RAII
- 没有构造函数和析构函数
- 不支持嵌套函数、嵌套类、嵌套命名空间等。
- 没有命名空间(有其他的替代机制)
- 不支持宏
- 不支持模板约束,模板元编程。
- 不支持union类型。
- 不需要前向声明
- 没有static的三层意思。
- 别名定义只能在顶部的import语句中。
- 可变性是简单的final,没有C++那么复杂的规则。
- 没有友员机制,默认internal访问级别。
- 不支持多继承,不支持私有继承
- ++i和i++只保留一个,并且不返回任何值。
- 不支持switch语句贯穿
- 不支持do while, goto语句。
其他
后面还会有闭包和运算符重载等,不再详细写,其他语法参考C++。
基本就是C+OO+内存安全。没有各种语法糖、没有怪异语法。
最后,heap语言只是开始设计和征求意见,并没有开始开发。 |
|