如何按值传递对象?

时间:2011-09-25 23:33:54

标签: parameter-passing pass-by-reference d pass-by-value

import std.stdio;

class IntegerContainer
{
    public int Integer = 1;
}

void DoubleInteger(IntegerContainer Container)
{
    Container.Integer *= 2;
}

void main()
{
    IntegerContainer Container = new IntegerContainer; // Internal integer defaults to one.
    DoubleInteger(Container); // Internal integer changes to two inside the function.
    writefln(Container.Integer); // Prints "2."
}

在D中,引用与值是类型的特征,而不是函数参数。来自C ++,这对我来说真的很糟糕。

看起来有一个ref关键字来强制接受struct的函数的传递引用。是否有通过值传递class es的等价物?

例如,假设我想创建一个函数函数,它返回自定义容器类的排序副本。在C ++中,这与使用Foo Sorted(Foo Object)一样简单,而不是Foo Sort(Foo& Object)。在没有手动复制对象的情况下,我认为无法在D中执行此操作。

3 个答案:

答案 0 :(得分:11)

类是设计的引用类型。它们不应该被价值所传递。它与Java和C#完全相同。但是,与Java和C#不同,D也有完整的用户定义值类型,因为它具有结构(C#也具有结构,但它们很多更受限制)。 C ++将两者混为一谈的事实导致object slicing等问题。

现在,当您想要复制引用类型时,显然次。解决方法是cloning。你给你的类一个clone函数,它返回它被调用的对象的副本。这样,您可以在需要时复制它,并且只在需要时才复制它。 Java和C#具有大多数类型实现的标准clone函数,但无论出于何种原因,D都没有。我不知道为什么。但是,为自己的类型自己声明这样的功能仍然很容易。它不会出现在Object上,它允许你在几乎任何类对象上使用它,而不用考虑你在Java和C#中可以做的实际类型。如果您愿意,您可以随时创建一个复制构造函数,但它不太灵活,因为您必须知道要复制的对象的类型,而使用clone,它可以是从clone类型派生的任何类型。 {1}}返回(对于Java和C#,它将是Object但是你在D中决定的是什么,因为函数是非标准的。)

答案 1 :(得分:4)

是的,只需使用结构而不是类。

但是如果你想复制一个对象,那么你必须自己实现克隆。请注意,D设计师没有做到这一点;它在C#中完全相同,在Java中非常相似。目标是防止对象被过度复制,这被视为C ++的缺点(因为它在代码中非常隐藏)。

答案 2 :(得分:3)

即使在C ++中:

Foo Sorted(Foo Object)

没那么有用。如果对象已经排序并且您不需要创建副本怎么办?

在D中,您需要为您的课程提供clone()部分内容,并在需要时调用。

否则使用Mehrdad提到的结构。

编辑:目前尚不清楚“复制对象”到底应该做什么。如果里面有对象数组,那么它会克隆那个数组吗?它包含的对象引用怎么样?实际上,D的作者Walter Bright先生默认不提供类实例的复制。