论坛首页 编程语言技术论坛

D语言备忘

浏览 2187 次
锁定老帖子 主题:D语言备忘
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-01-15  
学习的参照资料
http://www.d-programming-language-china.org/
对应版本
DMD 1.013(2007年4月12日)

0.
数组切片
char[][] args=[
    "main.exe",
    "zsp",
    "earth"
];
args[1..$])

1.
可以给引入模块一个本地名称
import io = std.stdio;
io.writefln("hello!");

2.
从一个模块中只导入专门符号,并绑定到当前名字空间
import std.stdio : writefln, foo = writef;

std.stdio.writefln("hello!");    // error, std is undefined
writefln("hello!");    // ok, writefln bound into current namespace
writef("world");    // 错误, writef is undefined
foo("world");    // ok, calls std.stdio.writef()

3.结合使用
import io = std.stdio : foo = writefln;

4.
int*[] x;        // x 是指向 int 的指针的数组
int[]* x;        // x 是指向 int 数组的指针
int[3][5] x;    // x 是有5个元素的数组,每个元素是有3个元素的 int 数组
int[3]*[5] x;    // x 是有5个元素的数组,每个元素是指向有3个元素的 int 的数组的指针
int function(char) x;    // x 是指向函数的指针,函数有一个 char 的参数,返回值类型是 int
int function(char)[] x;    // x 是指向函数的指针的数组,函数有一个 char 的参数,返回值类型是 int
int delegate(int) dg;    // dg 是函数的委托,委托不能用静态成员函数或者非成员函数初始化
5.
隐式类型推断
auto s = "string"; // s is type char[6]
auto y = 4u;       // y is type uint

6.
typedef 引入强类型,可以指定一个不同于其底层类型(underlying type)的初始值
typedef int myint = 7;

7.
别名,等价于C++中的typedef
alias abc.Foo.bar myint;

符号可以被声明为另一个符号的 别名
alias string.strlen mylen;
int len = mylen("hello");    // 实际上调用的是 string.strlen()

8.
别名还可以‘导入’一系列的重载函数,这样就可以在当前作用域中重载函数:
class A {
    int foo(int a) { return 1; }
}

class B : A {
    int foo( int a, uint b ) { return 2; }
}

class C : B {
    int foo( int a ) { return 3; }
    alias B.foo foo;
}

class D : C    {
}
void test()
{
    D b = new D();
    int i;

    i = b.foo(1, 2u);    // 调用 B.foo
    i = b.foo(1);        // 调用 C.foo
}

9.
typeof 用来获得一个表达式的类型
class A { }
class B : A
{
    typeof(this) x;    // x 被声明为 B 型
    typeof(super) y;    // y 被声明为 A 型
}

struct C
{
    typeof(this) z;    // z 被声明为 C* 型
}

10.
变量通常是显式初始化或设置为某类型的默认值。如果用void,变量并没有被子初始化,在设置值前使用它将为引发未定义.
int x = void;

11.
void no type -
bool boolean value false
byte signed 8 bits 0
ubyte unsigned 8 bits 0
short signed 16 bits 0
ushort unsigned 16 bits 0
int signed 32 bits 0
uint unsigned 32 bits 0
long signed 64 bits 0L
ulong unsigned 64 bits 0L
cent signed 128 bits (reserved for future use) 0
ucent unsigned 128 bits (reserved for future use) 0
float 32 bit floating point float.nan
double 64 bit floating point double.nan
real largest hardware implemented floating point size (Implementation Note: 80 bits for Intel CPUs) real.nan
ifloat imaginary float float.nan * 1.0i
idouble imaginary double double.nan * 1.0i
ireal imaginary real real.nan * 1.0i
cfloat a complex number of two float values float.nan + float.nan * 1.0i
cdouble complex double double.nan + double.nan * 1.0i
creal complex real real.nan + real.nan * 1.0i
char unsigned 8 bit UTF-8 0xFF
wchar unsigned 16 bit UTF-16 0xFFFF
dchar unsigned 32 bit UTF-32 0x0000FFFF

12.
在编译时打印出消息,赋值表达式 必须是字符串文字量
pragma(msg, "compiling...");

插入一条伪指令到目标文件,以链接赋值表达式指定的库。赋值表达式必须是字符串文字量。
pragma(lib, "foo.lib");

13.
如果成员函数是显式地通过引用 typeof(this) 调用的,会生成一个非虚函数调用:
  class A
{
    char get() { return 'A'; }

    char foo() { return typeof(this).get(); }
    char bar() { return this.get(); }
}

class B : A
{
    char get() { return 'B'; }
}

void main()
{
    B b = new B();

    b.foo();        // 返回 'A'
    b.bar();        // 返回 'B'
}

14.
import( AssignExpression )

赋值表达式必须在编译时计算为常量字符串。
文字内容被解释为文件名,读入文件,然后文件内容被精确转换为字符串文字量。
void foo()
{
    // 打印出foo.txt的所有内容
    writefln( import("foo.txt") );
}

15.
if ( is(func[]) )       //若为函数则不满足条件,因为数组不允许用于函数
if ( is(bar : int) )    //为或能隐式转换int
if ( is(bar == int) )   //为int

16.
静态if/else

static if ( is(bar T) )
    alias T S;
else
    alias long S;
   
17.
foreach正序
foreach_reverse倒序

char[] a;
foreach (int i, char c; a)
{
    printf("a[%d] = '%c'\n", i, c);
}

18.
double[char[]] a;            // 索引 类型是 char[],值 类型是 double
foreach (char[] s, double d; a)
{
    printf("a['%.*s'] = %g\n", s, d);
}

19.
如果聚集是一个结构或者类对象,则它由特定opApply 成员函数定义.
foreach_reverse行为由特定opApplyReverse成员函数定义,这此函数定义的类型必须和foreach语句相一致.

int opApply(int delegate(ref Type [, ...]) dg);
int opApplyReverse(int delegate(ref Type [, ...]) dg);

其中 Type 要同 foreach 声明中 标志符 中的 类型 匹配。
传递给 opApply 的委托类型中剩下的那些 类型 (上式中的“...”)对应于其余的多个 Foreach类型 。
结构或类中可以有多个不同的 opApply 函数,foreach语句 会使用类型匹配的函数,该函数的参数 dg 的参数类型要同 foreach语句 中对应的 Foreach类型 匹配。
opApply 的函数体遍历聚集的元素,并将它们作为参数依次传递给 dg 函数。
如果 dg 返回 0 ,则 opApply 继续应用于下一个元素。
如果 dg 返回一个非零值,opApply 必须停止遍历并返回那个值。
如果 opApply 顺利遍历了所有的元素,会返回 0 。

class Foo
{
    uint array[2];

    int opApply(int delegate(ref uint) dg)
    {  
        int result = 0;

        for (int i = 0; i < array.length; i++)
        {
            result = dg(array);
            if(result)break;
        }
        return result;
    }
}

void test()
{
    Foo a = new Foo();

    a.array[0] = 73;
    a.array[1] = 82;

    foreach (uint u; a)
    {
        printf("%d\n", u);
    }
}

将打印出:
QUOTE:
73
82

20.
ref 等价于 inout

21.
可以在 switch 表达式中使用字符串。例如:

char[] name;
switch (name)
{
    case "fred":
    case "sally":
    ...
}

goto 会跳转到以 标志符 为标号的语句处运行:
if (foo)
    goto L1;
    x = 3;
L1:
    x++;
第二种形式,goto default; ,会跳转到最内层 Switch语句 中的 Default语句 处。
第三种形式,goto case; ,会跳转到最内层 Switch语句 中的下一个 Case语句 处。
第四种形式,goto case 表达式; ,会跳转到包含带有 表达式 的 Case语句 的最内层 Switch语句 中那个 Case语句 处。

22.
struct Foo
{
    typedef int Y;
}
Y y;        // error, Y undefined
with (Foo)
{
    Y y;    // same as Foo.Y y;
}

23.
synchronize 语句用来在多线程情况下同步临界区内的语句。
synchronized { ... }

24.
int main()
{
    try
    {
        try
        {
            throw new Exception("first");
        }
        finally
        {
            printf("finally\n");
            throw new Exception("second");
        }
    }
    catch(Exception e)
    {
        printf("catch %.*s\n", e.msg);
    }
    printf("done\n");
    return 0;
}

25.
throw new Exception("message");

26.
scope用于资源释放,可以避免资源泄漏
{
    scope(exit) writef("1");
    scope(success) writef("2");
    scope(exit) writef("3");
    scope(success) writef("4");
   
    scope(failure) writef("7");
}
writefln();

写出: 4321

27.
Volatile 语句

没有什么代码活动能跨越 volatile 语句的边界。
在 语句 之前的所有内存写操作都保证在 语句 中或其后的内存读操作之前完成。
在 语句 之后的所有内存读操作都保证在 语句 中或其前的所有内存写完成之后执行。
volatile 语句不能保证原子性。如果要保证原子性,应该使用 synchronized 语句。

28.
数组属性
.ptr 返回指向数组第一个元素的指针。(d-programming-language-china.org注:pointer to first?)
.dup 创建一个同样大小的动态数组并将原数组的内容复制到新数组中。
.reverse 将数组中的元素按原来的逆序排列。返回数组。
.sort 将数组中的元素按照适当的方法排序。返回数组。

29.
关联数组的属性有:
.length 返回关联数组中值的个数。与动态数组不同的是,它是只读的。
.keys 返回动态数组,数组的元素是关联数组的关键字。
.values 返回动态数组,数组的元素是关联数组的值。   
.rehash 适当地重新组织关联数组以提高查找效率。例如,程序已经载入了符号表并将开始进行查找时,rehash 会提高效率。返回指向新数组的引用。

30.
struct结构可以被同类型值动态初始化
struct X { int a; int b; int c; int d = 7;}

static X z = { c:4, b:5, a:2 , d:5};
static X q = { 1, 2 };        // q.a = 1, q.b = 2, q.c = 0, q.d = 7

struct S
{    int a;

    static S opCall(int v)
    {
        S s;
        s.a = v;
        return s;
    }
}

S s = 3;    // sets s.a to 3

31.
union U { int a; double b; }
static U u = { b : 5.0 };        // u.b = 5.0

32.
tupleof是class中的变量数组
class Foo { int x; long y; }
void test(Foo foo)
{
    foo.tupleof[0] = 1;        // set foo.x to 1
    foo.tupleof[1] = 2;        // set foo.y to 2
    foreach (x; foo.tupleof)
    writef(x);        // prints 12
}

33.
类不变量用来指定类的必须总是为真的特征.不变量中的代码不应该调用任何非静态公有类成员函数.
class Date
{
    int day;
    int hour;

    invariant
    {
        assert(1 <= day && day <= 31);
        assert(0 <= hour && hour < 24);
    }
}

34.
一个编译器开关,如DMD用-unittest,使单元测试代码编译并整合到可执行文件中。程序中所有类的 test() 函数将在静态初始化之后,maiin()函数调用之前被调用。
unittest
{
    ...测试代码...
}

35.
enum { A, B = 5+7, C, D = 8, E }
这令 A=0、B=12、C=13、D=8、E=9。
.init           枚举第一个成员的值
.min            枚举的最小值
.max            枚举的最大值

36.
按照定义,如果契约先验条件被违反,则过程体(body)将受到错误的参数。
这将抛出一个 AssertError 异常。
如果契约后验条件被违反,则意味着过程体中有一个 bug ,将抛出一个 AssertError 异常。

long square_root(long x)
in
    {
        assert(x >= 0);
    }
out (result)
//如果函数返回 void,即没有结果,那么 out 子句中自然也没有 result 的声明。在这种情况下,使用:out{}
    {
        assert((result * result) <= x && (result+1) * (result+1) >= x);
    }
body
    {
        return cast(long)std.math.sqrt(cast(real)x);
    }
   
37.
预定义版本

X86 Intel 和 AMD 的 32 bit 处理器
X86_64  AMD 和Intel 的64 bit 处理器
Windows Microsoft Windows 系统
Win32   Microsoft 32 bit Windows 系统
Win64   Microsoft 64 bit Windows 系统
linux   所有的 linux 系统
LittleEndian    字节序,低位优先
BigEndian   字节序,高位优先
none    未定义;用来禁用某段代码
all     总是定义(方便调试?); used as the opposite of none

38.
debug
debug ( Integer )
debug ( Identifier )

39.
static assert(0);

40.
Error 类有一个叫做 toString() 的纯虚函数,它返回一个 char[] 类型的人类可读的错误描述。

41.
复数文字量没有自身特殊的语法,只需写成实数类型和虚数类型相加即可:
ireal j = 1.3i;
cdouble cd = 3.6 + 4i;
creal c = 4.5 + 2i;

42.
嵌入文档注释:
  /// 单行文档注释

/** 同样是. */

/+ 也是注释+/

/**
一条概要注释.
*/

int a;    /// a的文档,b没有文档
int b;

/** c和d的文档 */
/** 更多c和d的文档 */
int c;
/** ditto */
int d;

/* e的文档 */ int e;
int f;    /// ditto

/** g的文档 */
int g; ///更多g的文档

/// C和D文档
class C
{
    int x;    ///    C.x的文档

    /** C.y 和C.z的文档 */
    int y;
    int z;    /// ditto

/// ditto
class D
{
}

文档注释由连续的节组成。每节由节名开始,节名是非空白字符后面紧跟':'。节名不区分大小写。
1.1 Summary摘要
第一节是摘要,没有节名。也就是第一段直到空行或一个节名。虽然摘要可以任意长度,不过你可以让它保持在一行内。摘要是可选的。
1.2 Descripti描述

第二节是描述。从摘要开始直到节名或者注释结束。
尽管描述是可选的,但存在描述的话必须存在摘要。
/***********************************
* Brief summary of what
* myfunc does, forming the summary section.
*
* First paragraph of synopsis description.
*
* Second paragraph of
* synopsis description.
*/

43.
为了格式的一致性和可预测性,有一些标准节。
  Bugs: Doesn't work for negative values.
  Date: March 14, 2003
  Deprecated: superseded by function bar()
 
  Examples:
  --------------------
  writefln("3"); // writes '3' to stdout
  用至少三个连字符来画出嵌入代码的范围
  --------------------
   
Historys initial version
    V2 added feature X

Liense se freely for any purpose

Returns: The contents of the file.

See_Also:foo, bar, http://www.digitalmars.com/d/phobos/index.html

Standards: Conforms to DSPEC-1234

Throws:列出什么情况下抛出什么异常

Version: 1.6a列出明的版本

Params:
    x =    is for this
    y =    is for that
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics