7

我知道字符串是不可变的,所以当您更改字符串引用的值时,.NET 会在堆上创建一个全新的字符串。

但是如果你不改变字符串引用的值呢?相反,您只需将它传递给一个函数ByVal——这个操作是否也会复制堆上的字符串值?我的倾向是“不”,但我想确认一下。

例如:

Public Function IsStringHello(ByVal test As String) As Boolean 
  Return (String.Compare(test, "Hello") = 0)    
End Function

调用程序:

Dim myWord as String = "Blah"
Dim matchesHello as Boolean = IsStringHello(myWord)

我知道myWord按值传递会复制对“Blah”的引用,但由于我没有尝试更改字符串本身,它会在堆上制作另一个字符串副本吗?

4

6 回答 6

9

顺便说一句,字符串实习与此完全无关。将参数传递给函数的规则对于所有引用类型(实际上是所有类型)都是相同的,无论它们在内部如何管理。

规则很简单,并且您已经正确说明:按值传递复制引用,而不是目标。这里没有堆空间被复制。

于 2009-06-26T18:50:36.657 回答
4

不,它仍然使用对“Blah”的引用副本。
是什么让你觉得,它会?

附带说明一下,字符串是实习的。

string s = "hello";
string t = "hello";

s & t 都引用同一个字符串(因为它是实习的)。如果你修改 s 或 t,它会创建一个新的字符串,那么。

于 2009-06-26T18:45:09.053 回答
2

传递对象 ByVal 会创建指针的副本,而不是对象本身。这是一个演示:

Module Module1
    Dim original As String = "Hello world"

    Sub PassByReferenceTest(ByVal other As String)
        Console.WriteLine("object.ReferenceEquals(original, other): {0}", _
            Object.ReferenceEquals(original, other))
    End Sub

    Sub Main()
        PassByReferenceTest(original)
        Console.ReadKey(True)
    End Sub
End Module

该程序输出以下内容:

object.ReferenceEquals(original, other): True

所以,原始字符串和我们传值的字符串在内存地址中存在同一个地址。您没有复制字符串本身。

于 2009-06-26T19:13:50.340 回答
0

很短,没有。它将 ref 传递给字符串。字符串本身只有一个实例。

于 2009-06-26T18:49:11.670 回答
0

string 是一个引用类型。如果按值传递,则传递的是引用的值。

在堆上获得另一个副本的唯一方法是更改​​变量的值。

于 2009-06-26T18:57:49.733 回答
0

一个类型的变量System.String有效地保存了一个“object-ID”。假设那Object #1934是一个带有字符的字符串"Blah",而你说Dim myWord As String = "Blah"。然后编译器将存储Object #1934myWord. 然后调用IsStringHello(myWord)将导致调用该函数,其test参数等于Object #1934。在您的示例中,内存中将有两个类型System.String的变量 -myWordtest,并且两者都将保存 content Object #1934

于 2012-06-27T22:49:24.620 回答