热度 10| ||
原文链接 https://stackoverflow.com/q/31017629/13685812
通常来说,task或者function的形参声明为input时,input类型的形参仅仅是得到了一份拷贝;
当task或者function的形参声明为output时,output类型的形参会在return的时候将此形参的拷贝复制给接收对象。
而inout类型的形参,则会在被调用时得到一份拷贝,并在return的时候将形参的拷贝复制给接收对象。
对于ref类型的形参,则传入的是引用,而不是一份拷贝。因此,ref类型的形参,具有更严格的数据类型要求。由于传入的是引用,当task或者function对这个参数进行修改时,外部是可见的。
对于一个需要消耗时间的task来讲,inout和ref的形参,具有很大的区别。在task运行期间,ref类型的参数,外部一直是可见,并且外部对这个引用所指向的内存空间的值的修改,task也是可见的。而对于inout类型的形参,task中仅仅是得到的一份拷贝,因此,在task运行期间,尽管这个参数对应的外部值发生变化,task中也是不可见的。当然,task中对这个值进行修改时,外部也是不可见的。当task结束时,才会将这个参数的拷贝传递给外部,这时,外部才能得到这个值。
上例可以清楚看到inout 和 ref 的区别:
1,在0ns,line10和line11启动两个initial块;line12初始化A B为z;
2,在1ns,line10调用my_task;line4打印 arg1 =z arg2 =z;
3,在2ns,line13 对A B分别赋值为0;
4,在6ns,line6打印arg1 =z arg2 =0;(B的值此时为0,准确的说,在2ns时,arg2已经可见B的值0)
5,在7ns,line15打印A = 0,B=1;(arg2为1,对外部可见,故B为1。准确的说,在6ns时,line7使B已得到值1)
6,在11ns,line8打印arg1 =1 arg2 =1;(task退出,arg1的拷贝传递给了A)
7,在12ns,line12打印A = 1,B=1;(arg1为1,传递给A)
需要特别注意的一点是,如果形参是一个class类型的,那么这已经是一个类句柄了,也就是说,task中对这个class进行修改时,外部也是看见的,这可能并不是所期望的,应当特别小心。同时需要说明,如果想要在task或者function中,对类句柄进行修改(如new一块新的内存空间),那么,应该把这个形参声明为ref。
最后,如果需要传递一个特别大的参数给task或者function,使用ref类型是一个很好的选择,可以节省内存资源。