Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 传递字符串时ByRef与ByVal的性能_Vb.net_Performance_String_Byref_Byval - Fatal编程技术网

Vb.net 传递字符串时ByRef与ByVal的性能

Vb.net 传递字符串时ByRef与ByVal的性能,vb.net,performance,string,byref,byval,Vb.net,Performance,String,Byref,Byval,阅读让我怀疑那里的评论是否在性能方面适用于Strings。既然字符串是在传递之前复制的,那么传递字符串ByRef不是更有效(如果被调用方不需要字符串课程的副本)吗 谢谢, CFP > >编辑:< /强>考虑此代码,这使我认为有某种拷贝正在进行: Sub Main() Dim ByValStr As String = "Hello World (ByVal)!" Dim ByRefStr As String = "Hello World (ByRef)!" fooval

阅读让我怀疑那里的评论是否在性能方面适用于
Strings
。既然字符串是在传递之前复制的,那么传递字符串
ByRef
不是更有效(如果被调用方不需要字符串课程的副本)吗

谢谢,
CFP

<> > >编辑:< /强>考虑此代码,这使我认为有某种拷贝正在进行:

Sub Main()
    Dim ByValStr As String = "Hello World (ByVal)!"
    Dim ByRefStr As String = "Hello World (ByRef)!"

    fooval(ByValStr)
    fooref(ByRefStr)

    Console.WriteLine("ByVal: " & ByValStr)
    Console.WriteLine("ByRef: " & ByRefStr)

    Console.ReadLine()
End Sub


Sub fooval(ByVal Str As String)
    Str = "foobar"
End Sub

Sub fooref(ByRef Str As String)
    Str = "foobar"
End Sub
它输出:

ByVal: Hello World (ByVal)!
ByRef: foobar
字符串在传递之前不会被复制。字符串是引用类型,尽管它们的行为有点像值类型

您应该根据您的需求使用最有意义的东西。(如果您的需求恰巧是“必须以牺牲所有其他考虑因素为代价压缩最后一纳秒的性能”,那么您可能应该破解分析器,而不是询问stackoverflow!)


这几乎肯定是您不必担心的事情,我怀疑是否存在显著的性能差异。只有在传递大值类型时,我才有可能看到差异。

我决定自己检查一下,以得到更“科学”的答案。它们是一样的。如果我使用下面的代码,ByVal大约比ByRef慢2%。然而,如果我交换它们,这样我在ByVal之前计时ByRef,那么ByRef大约慢2%。因此,在本例中,比ByRef或ByVal更重要的是它们的运行顺序:)


要理解类类型(包括字符串)的行为,请将所有类类型参数、变量、字段和数组元素等视为持有“对象ID”。如果
Foo
string
类型的变量,则语句
Foo=12345.ToString()
将创建一个新的对象id(假设为对象id#197),并使用该id创建一个类型为
string
的新对象,其中包含五个字符
“12345”
。然后,它将
对象ID#197
存储到变量
Foo
中。如果调用带有非ref参数的例程
param
,并将
Foo
传递给它,那么
param
将是一个局部变量,保存
对象ID#197
。语句
param+=“6”
将创建一个字符串类型的新对象(例如对象ID#521),包含六个字符
“123456”
,并将
对象ID#521
存储到
参数中。请注意,
Foo
仍保留
对象ID#197
,并且该对象仍保留五个字符的字符串
“12345”

如果
param
已被
ref
传递,则语句
param+=“6”
会将
对象ID#521
存储到
Foo
中。它仍然不会对Object#197造成任何可见的更改,除非可能使其符合垃圾收集的条件(如果
Foo
是Object#197的唯一引用,覆盖它将意味着宇宙中任何地方都不再存在对该对象的任何引用)


请注意,即使不考虑对象ID,也很容易对不可变的类类型(如
string
)进行推理,因为更改字符串变量表示的字符序列的唯一方法是在其中存储不同的对象ID。然而,在处理可变类类型时,考虑对象ID变得至关重要。传递一个class type
Car
的变量,而不是通过ref,将相当于将VIN从一张纸条复制到另一张纸条,然后将后一张纸条交给一些车间工人,并要求他们对其进行处理。如果第一份文件最初确定了一辆VIN为15934的红色汽车,那么当工人们完成工作时,第一份文件可能会确定一辆VIN为15934的蓝色汽车,但它将是同一辆汽车。工人们对他们收到的纸条无能为力,对汽车也无能为力,这将改变第一份报纸提到的汽车。另一方面,通过引用传递参数更像是车间工人在一张纸上写上VIN,然后在完成后从他们那里取回纸张。如果工人们可以划掉VIN并写下另一个,那么当他们返回纸条时,它可能指的是同一辆车或不同的车;如果它指的是另一辆车,它最初指的那辆车可能被修改过,也可能没有被修改过,论文最后指的那辆车可能与原来的车没有任何相似之处。

但是如果你将
ByVal
字符串
mystr
传递给
foobar
并且在
foobar
中设置
mystr=“你好“
,则
mystr
的初始值不会更改。。。所以一定存在某种复制,不是吗?字符串是引用类型,所以不管是使用
ByVal
还是
ByRef
,都在传递引用。不同之处在于,当您传递
ByVal
时,您传递的是一个包含原始引用副本的新变量,因此对该变量的任何更改本质上都是私有的;当您传递
ByRef
时,您传递的是原始变量,因此对该变量的任何更改在外部都可见。这意味着当您传递
ByVal
并设置
mystr=“hello”
时,您只需覆盖变量
mystr
中包含的指针,指向
“hello”
,但是不改变原始指针本身吗?对新字符串“hello”的引用被分配给传递的变量-如果传递了
ByRef
,那么该变量就是原始的外部变量;如果您传递了
ByVal
,那么它只是方法的局部变量,并且原始的外部变量不受影响;如果一个人不能改变美国
Function CreateString()

    Dim i As Integer
    Dim str As String = ""

    For i = 1 To 10000
        str = str & "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    Next i

    Return str
End Function

Sub fooval(ByVal Str As String)
    Str = Str & "foobar"
End Sub

Sub fooref(ByRef Str As String)
    Str = Str & "foobar"
End Sub

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim str As String = CreateString()
    Dim stopWatch As New Stopwatch
    Dim i As Integer

    stopWatch.Start()
    For i = 1 To 1000
        fooval(str)
    Next i
    stopWatch.Stop()
    Dim valtime As Long = stopWatch.ElapsedMilliseconds

    stopWatch.Restart()
    For i = 1 To 1000
        fooref(str)
    Next i
    stopWatch.Stop()
    Dim reftime As Long = stopWatch.ElapsedMilliseconds

    MsgBox("Val took " & valtime & " milliseconds and Ref took " & reftime & " milliseconds")
End Sub