传递给方法时struct没有通过引用传递(Struct is not passed by refer

2019-09-27 01:23发布

struct Data {
    public int x;
}

void change_x(Data data) {
    data.x = 123;
}

Data a = Data();
change_x(a);
print("%d", a.x); // 0

但文件说:

当结构类型的实例被传递到方法,复制不进行。 相反,该实例的引用传递。
-在https://wiki.gnome.org/Projects/Vala/Manual/Types

怎么了?

Answer 1:

我想你指的引用的文字或者是过时的或者是错误的开始。

你必须使用ref (或out ,如果你想让它按引用传递(因此得名) ref )。

struct Data {
    public int x;
}

void change_x (ref Data data) {
    data.x = 123;
}

int main () {
    Data a = Data ();
    change_x (ref a);
    print ("%d\n", a.x);
    return 0;
}


Answer 2:

在瓦拉结构是实现为转让副本,并通过引用传递。 所以,你可以认为你的例子作为复制结构,因为它被分配到一个参数的函数,然后该副本是通过引用传递。 这是正在发生的事情在生成的C代码在幕后,但是从侧面瓦拉这意味着一个结构是值类型。 只有一个C库接口时是有用知道结构的副本是通过引用传递。 从手动的报价是指结构的方法,但我们看一下之前在细节让我们了解更多的关于价值和引用类型。

瓦拉,如Java,C#等多种文字,有两种数据类型:值类型和引用类型。

值类型是按值传递

当一个值类型被作为参数传递给函数或方法,那么其值作为参数传递通过,但它是值的副本。 如果函数或方法继续修改​​它收到的参数,这是不会改变调用代码的价值。 该代码被封装。

下面的例子:

void main () {
        int a = 23;
        print ("Initial value: %i\n", a);
        modify_example (a);
        print ("Final value: %i\n", a);
}

void modify_example (int x) {
        x += 100;
}

生产:

Initial value: 23
Final value: 23

虽然这一数值是在函数修改不修改也从调用代码的值。

值类型可以通过引用传递

代替值传递给函数或方法中的用途的ref关键字将传递到值的引用。 这为呼叫值的别名。 其结果是相同的存储空间两个标识符。

仅仅通过增加ref关键字下面的例子:

void main () {
        int a = 23;
        print ("Initial value: %i\n", a);
        modify_example (ref a);
        print ("Final value: %i\n", a);
}

void modify_example (ref int x) {
        x += 100;
}

现在生产:

Initial value: 23
Final value: 123

通过调用modify_example ()的副作用是在调用代码也改变数值。 利用ref使这个明确的,并且可以使用的一种方式的函数返回多个值,但在本实施例中这将是更清楚return通过参考修改后的值,而不是通过。

引用类型总是通过引用传递

对象是引用类型。 这个例子没有使用明确的ref ,但该值在调用代码更改:

void main () {
        var a = new ExampleReferenceType (23);
        print ("Initial value: %i\n", a.value);
        modify_example (a);
        print ("Final value: %i\n", a.value);
}

class ExampleReferenceType {
        public int value;

        public ExampleReferenceType (int default = 0) {
                this.value = default;
        }
}

void modify_example (ExampleReferenceType x) {
        x.value += 100;
}

这将产生:

Initial value: 23
Final value: 123

这样修改的对象可以追踪缺陷时,会引起问题。 这是创造价值的对象不可变的优点。 这也只会在构造函数中设置的值,使得各个领域私有的,只能使用一个属性来获取价值,而不是把它完成。

作为结构值类型

下面的代码:

void main () {
        ExampleStruct a = { 23 };
        print ("Initial value: %i\n", a.value);
        modify_example (a);
        print ("Final value: %i\n", a.value);
}

private struct ExampleStruct {
        public int value;
}

void modify_example (ExampleStruct x) {
        x.value += 100;
}

类似于您的代码和生产:

Initial value: 23
Final value: 23

这是瓦拉相同的行为与其他值类型,但如果你看看C代码使用--ccode开关与valac ,你会看到该结构被复制,并通过引用传递。 当你需要了解瓦拉如何维护的C ABI(应用程序二进制接口)这是相关的。

结构方法

本手册你做参考可能不是很清楚,但我认为这涉及到结构中的方法。 如果modify_example移动结构定义中:

void main () {
        ExampleStruct a = { 23 };
        print ("Initial value: %i\n", a.value);
        a.modify_example ();
        print ("Final value: %i\n", a.value);
}

private struct ExampleStruct {
        public int value;

        public void modify_example () {
                this.value += 100;
        }
}

这个现在生产:

Initial value: 23
Final value: 123

该方法目前经营上的实例。

[SimpleType的]的Structs

从您还引述本手册的部分下一句说:

这种行为可以通过声明的结构是一个简单的类型而改变。

因此,对于完整性这里是最后一个例子:

void main () {
        ExampleStruct a = { 23 };
        print ("Initial value: %i\n", a.value);
        a.modify_example ();
        print ("Final value: %i\n", a.value);
}

[SimpleType]
private struct ExampleStruct {
        public int value;

        public void modify_example () {
                this.value += 100;
        }
}

并且这产生:

Initial value: 23
Final value: 23

虽然该方法是在结构内仍限定的实例是通过值而不是引用传递。

简单型结构是基本值类型如何在瓦拉定义,例如intint64 。 如果你想定义的结构方法作用于一个简单的类型结构实例,则该方法将必须被定义为返回包含修改后的值的新实例。

结论

结构是在瓦拉值类型,但它是有用的知道他们是如何实现的理解与C ABI的兼容性。 在您的示例结构体表现为值类型,但被复制并通过引用传递在C ABI的条款。 该帖似乎最相关的结构中定义的方法。



文章来源: Struct is not passed by reference when passed to a method
标签: struct vala