哪个更快? ByVal 还是 ByRef?

发布于 2024-07-10 21:21:28 字数 237 浏览 7 评论 0原文

在 VB.NET 中,对于方法参数使用 ByValByRef 哪个更快?

另外,哪个在运行时消耗更多资源(RAM)?


我通读了这个问题,但答案不适用或不具体足够的。

In VB.NET, which is faster to use for method arguments, ByVal or ByRef?

Also, which consumes more resources at runtime (RAM)?


I read through this question, but the answers are not applicable or specific enough.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

老娘不死你永远是小三 2024-07-17 21:21:28

Byval 和 ByRef 参数的使用应基于需求和对它们如何工作的了解,而不是基于速度。

http://www.developer.com/net/vb/article.php/3669066

回应 Slough 的评论 -

哪个在运行时消耗更多资源?

参数在堆栈上传递。 堆栈非常快,因为它的内存分配只是一个指针增量来保留新的“帧”或“分配记录”。 大多数 .NET 参数不会超过机器寄存器的大小,如果使用任何“堆栈”空间来传递参数,那么就很小。 事实上,基本类型和指针都是在堆栈上分配的。 .NET 中的堆栈大小限制为 1 MB。 这应该可以让您了解参数传递消耗的资源有多少。

您可能会发现这一系列文章很有趣:

通过堆栈分配提高性能(.NET 内存管理:第 2 部分)

哪个更快? ByVal 或 ByRef。

准确和完美地测量是很困难的 - 取决于测量的上下文,但我编写的调用方法 1 亿次的基准得出以下结果:

  • 引用类型 - 通过 ByRef: 420 ms
  • 引用类型 - Passed ByVal:382 ms
  • 值类型 - Passed ByRef:421 ms
  • 值类型 - Passed ByVal:416 ms
Public Sub Method1(ByRef s As String)
    Dim c As String = s
End Sub

Public Sub Method2(ByVal s As String)
    Dim c As String = s
End Sub

Public Sub Method3(ByRef i As Integer)
    Dim x As Integer = i
End Sub

Public Sub Method4(ByVal i As Integer)
    Dim x As Integer = i
End Sub

Sub Main()

    Dim s As String = "Hello World!"
    Dim k As Integer = 5

    Dim t As New Stopwatch

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method1(s)
    Next
    t.Stop()

    Console.WriteLine("Reference Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method2(s)
    Next
    t.Stop()

    Console.WriteLine("Reference Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method3(i)
    Next
    t.Stop()

    Console.WriteLine("Value Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method4(i)
    Next
    t.Stop()

    Console.WriteLine("Value Type - ByVal " & t.ElapsedMilliseconds)

    Console.ReadKey()

End Sub

注释每个方法中的变量和赋值 -

  • 引用类型 - Passed ByRef:389 ms
  • 引用类型 - Passed ByVal: 349 毫秒
  • 值类型 - 通过 ByRef 传递:416 毫秒
  • 值类型 - 通过 ByVal 传递:385 毫秒

我们可以得出结论,传递引用类型(字符串、类)ByVal 将节省一些时间。 您可能还会说传递值类型(整数、字节)-ByVal 会节省一些时间。

同样,在宏伟的计划中,时间可以忽略不计。 更重要的是正确使用 ByVal 和 ByRef 并了解“幕后”发生的事情。 在例程中实现的算法肯定会多次影响程序的运行时间。

Byval and ByRef arguments should be used based on requirements and knowledge of how they work not on speed.

http://www.developer.com/net/vb/article.php/3669066

In response to a comment by Slough -

Which consumes more resources at runtime?

Parameters are passed on the stack. The stack is very fast, because its memory allocation is simply a pointer increment to reserve a new "frame" or "allocation record." Most .NET parameters do not exceed the size of a machine register so little if any "stack" space is used to pass parameters. In fact basic types and pointers are both allocated on the stack. The stack size in .NET is limited to 1 MB. This should give you an idea of how few resources are consumed by parameter passing.

You may find this series of articles interesting:

Improving Performance Through Stack Allocation (.NET Memory Management: Part 2)

Which is faster? ByVal or ByRef.

It is difficult at best to measure accurately and fairy - depending on the context of your measurement, but a benchmark I wrote calling a method 100 million times came up with the following:

  • Reference Type - Passed ByRef: 420 ms
  • Reference Type - Passed ByVal: 382 ms
  • Value Type - Passed ByRef: 421 ms
  • Value Type - Passed ByVal: 416 ms
Public Sub Method1(ByRef s As String)
    Dim c As String = s
End Sub

Public Sub Method2(ByVal s As String)
    Dim c As String = s
End Sub

Public Sub Method3(ByRef i As Integer)
    Dim x As Integer = i
End Sub

Public Sub Method4(ByVal i As Integer)
    Dim x As Integer = i
End Sub

Sub Main()

    Dim s As String = "Hello World!"
    Dim k As Integer = 5

    Dim t As New Stopwatch

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method1(s)
    Next
    t.Stop()

    Console.WriteLine("Reference Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method2(s)
    Next
    t.Stop()

    Console.WriteLine("Reference Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method3(i)
    Next
    t.Stop()

    Console.WriteLine("Value Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method4(i)
    Next
    t.Stop()

    Console.WriteLine("Value Type - ByVal " & t.ElapsedMilliseconds)

    Console.ReadKey()

End Sub

Commenting out the variable and assignment in each method -

  • Reference Type - Passed ByRef: 389 ms
  • Reference Type - Passed ByVal: 349 ms
  • Value Type - Passed ByRef: 416 ms
  • Value Type - Passed ByVal: 385 ms

One could conclude that passing reference types (strings, classes) ByVal will save some time. You might also say that passing value types (integer, byte) - ByVal will save some time.

Again the time is negligible in the grand scheme of things. What's more important is using ByVal and ByRef properly and understanding what's going on "behind the scenes." The algorithms implemented in your routines will most surely affect the runtime of your program many times more.

百合的盛世恋 2024-07-17 21:21:28

如果您使用非常大的值类型(例如 Guid 相当大),则通过引用传递参数可能会稍微快一些。 在其他情况下,当您通过引用传递而不是通过值传递时,可能会出现更多复制等 - 例如,如果您有一个字节参数,那么一个字节显然小于四个或八个字节如果您通过引用传递指针,则该指针将采用该指针。

实际上,您几乎不必担心这一点。 编写尽可能可读的代码,这几乎总是意味着通过值而不是引用传递参数。 我很少使用 ByRef。

如果您想提高性能并认为 ByRef 会对您有所帮助,请在投入使用之前仔细对其进行基准测试(根据您的实际情况)。

编辑:我在另一个(之前已接受,现在已删除)答案的评论中注意到,对于值类型时 ByRef 与 ByVal 的含义存在很多误解。 我有一篇关于参数传递的文章,多年来它很受欢迎 - 它是用 C# 编写的术语,但相同的概念也适用于 VB.NET。

If you're using a very large value type (Guid is pretty big, for example) it may be very slightly faster to pass a parameter by reference. In other cases, there may be more copying etc when you pass by reference than by value - for instance, if you've got a byte parameter, then one byte is clearly less than the four or eight bytes that the pointer would take if you passed it by reference.

In practice, you should almost never worry about this. Write the most readable code possible, which almost always means passing parameters by value instead of reference. I use ByRef very rarely.

If you want to improve performance and think that ByRef will help you, please benchmark it carefully (in your exact situation) before committing to it.

EDIT: I note in the comments to another (previously accepted, now deleted) answer that there's a great deal of misunderstanding about what ByRef vs ByVal means when it comes to value types. I have an article about parameter passing which has proved popular over the years - it's in C# terminology, but the same concepts apply to VB.NET.

绝不服输 2024-07-17 21:21:28

这取决于。 如果您传递一个对象,那么它已经在传递一个指针。 这就是为什么如果你传入一个 ArrayList(例如)并且你的方法向 ArrayList 添加一些东西,那么调用代码也会将相同的对象放入传入的 ArrayList 中,因为它是相同的 ArrayList。 唯一不传递指针的情况是,将具有内部数据类型(例如 int 或 double)的变量传递到函数中时。 此时,它会创建一个副本。 然而,这些对象的数据量非常小,因此在内存使用或执行速度方面几乎不会产生任何影响。

It depends. If you are passing an object, it is already passing a pointer. That's why if you pass in an ArrayList (for instance) and your method adds somthing to the ArrayList, then the calling code also has the same object into it's ArrayList, that was passed in, because it's the same ArrayList. The only time that it doesn't pass a pointer, is when you pass a variable with an intrinsic data type, like an int, or a double, into the function. At that point, it creates a copy. However, the data size of these objects is so small, that it would hardly make a difference either way, in terms of memory usage or speed of execution.

假装爱人 2024-07-17 21:21:28

如果传递引用类型,ByRef 会更慢。

这是因为传入的是一个指向指针的指针。 对对象上字段的任何访问都需要取消引用额外的指针,这将需要一些额外的时钟周期才能完成。

如果要传递值类型,那么如果结构有许多成员,则 byref 可能会更快,因为它只传递单个指针,而不是复制堆栈上的值。 在访问成员方面,byref 会更慢,因为它需要进行额外的指针取消引用(sp->pValueType->member 与 sp->member)。

大多数时候在 VB 中您不必担心这一点。

在 .NET 中,很少有具有大量成员的值类型。 它们通常很小。 在这种情况下,传递值类型与向过程传递多个参数没有什么不同。 例如,如果您有按值传入 Point 对象的代码,那么它的性能将与采用 X 和 Y 值作为参数的方法相同。 看到 DoSomething(x 作为整数,y 作为整数) 可能不会引起性能问题。 事实上,你可能永远不会三思而后行。

如果您自己定义大值类型,那么您可能应该重新考虑将它们转换为引用类型。

唯一的其他区别是执行代码所需的指针间接数量的增加。 您很少需要在该级别进行优化。
大多数时候,要么存在您可以解决的算法问题,要么您的性能瓶颈与 IO 相关,例如等待数据库或写入文件,在这种情况下,消除指针间接对您没有多大帮助。

因此,我建议您不要关注 byval 或 byref 是否更快,而应该真正关注为您提供所需语义的内容。 一般来说,除非您特别需要 byref,否则最好使用 byval。 它使程序更容易理解。

If you are passing in a reference type, ByRef is slower.

This is because what gets passed in is a pointer to a pointer. Any access to fields on the object requires dereferencing an extra pointer , which will take a few extra clock cycles to complete.

If you are passing a value type, then byref may be faster if the structure has many members, because it only passes a single pointer rather than copying the values on the stack. In terms of accessing members, byref will be slower because it needs to do an extra pointer dereference (sp->pValueType->member vs sp->member).

Most of the time in VB you shouldn't have to worry about this.

In .NET it is rare to have value types with a large number of members. They are usually small. In that case, passing in a value type is no different than passing in multiple arguments to a procedure. For example, if you had code that passed in a Point object by value, it's perf would be the same as a method that took X and Y values as parameters. Seeing DoSomething(x as integer, y as integer) would probably not cause perf concerns. In fact, you would probably never think twice about it.

If you are defining large value types your self, then you should probably reconsider turning them into reference types.

The only other difference is the increase in the number of pointer indirections required to execute the code. It is rare that you ever need to optimize at that level.
Most of the time, there are either algorithmic issues you can address, or your perf bottleneck is IO related, such as waiting for a database or writing to a file, in which case eliminating pointer indirections isn't going to help you much.

So, instead of focusing on wheter byval or byref is faster, I would recommend that you should really be focusing on what gives you the semantics that you need. In general, it's good idea to use byval unless you specifically need byref. It makes the program much easier to understand.

挽清梦 2024-07-17 21:21:28

虽然我对 .NET 的内部了解不多,但我将讨论我对编译语言的了解。 这不适用于引用类型,并且对于值类型可能不完全准确。 如果您不知道值类型和引用类型之间的区别,则不应阅读本文。 我假设 32 位 x86(带有 32 位指针)。

  • 传递小于 32 位的值仍使用堆栈上的 32 位对象。 该对象的一部分将“未使用”或“填充”。 传递此类值并不比传递 32 位值使用更少的内存。
  • 传递大于 32 位的值将比指针使用更多的堆栈空间,并且可能需要更多的复制时间。
  • 如果对象按值传递,则被调用者可以从堆栈中获取该对象。 如果对象是通过引用传递的,则被调用者必须首先从堆栈中获取该对象的地址,然后从其他地方获取该对象的值。 价值意味着少一次获取,对吧? 好吧,实际上提取需要由调用者完成 - 但是调用者可能已经因为不同的原因而必须进行提取,在这种情况下,提取将被保存。
  • 显然,对按引用值所做的任何更改都必须保存回 RAM,而按值参数可以被丢弃。
  • 按值传递比按引用传递更好,仅将参数复制到局部变量中并且不再触及它。

结论:

了解 ByVal 和 ByRef 实际为您做什么以及了解值类型和引用类型之间的差异比考虑性能更重要。 第一条规则是使用更适合您的代码的方法

对于大值类型(超过 64 位),请按引用传递,除非按值传递有优势(例如更简单的代码、“它只是有意义”或接口一致性)。

对于较小的值类型,传递机制对性能没有太大影响,而且无论如何,很难预测哪种方法会更快,因为它取决于对象大小、调用者和被调用者如何使用对象,甚至缓存考虑因素。 只做对你的代码有意义的事情。

While I don't know much about the internals of .NET, I'll discuss what I know about compiled languages. This does not apply to reference types, and may not be completely accurate about value types. If you don't know the difference between value types and reference types, you shouldn't read this. I'll assume 32-bit x86 (with 32-bit pointers).

  • Passing values smaller than 32-bits still uses a 32-bit object on the stack. Part of this object will be "unused" or "padding". Passing such values doesn't use less memory than passing 32-bit values.
  • Passing values larger than 32-bits will use more stack space than a pointer, and probably more copying time.
  • If an object is passed by value, the callee can fetch the object from the stack. If an object is passed by reference, the callee must first fetch the object's address from the stack, and then fetch the object's value from elsewhere. By value means one less fetch, right? Well, actually the fetch needs to be done by the caller - however the caller may have already had to fetch for different reasons in which case a fetch is saved.
  • Obviously any changes made to a by-reference value must be saved back to RAM, whereas a by-value parameter can be discarded.
  • It's better to pass by value, than to pass by reference only to copy the parameter into a local variable and not touch it again.

The verdict:

It's much more important to understand what ByVal and ByRef actually do for you, and understand the difference between value and reference types, than to think about performance. The number one rule is to use whichever method is more appropriate to your code.

For large value types (more than 64 bits), pass by reference unless there is an advantage to passing by value (such as simpler code, "it just makes sense", or interface consistency).

For smaller value types, the passing mechanism doesn't make much difference to performance, and anyway it's hard to predict which method will be faster, since it depends on the object size, how the caller and callee use the object, and even cache considerations. Just do whatever makes sense for your code.

等你爱我 2024-07-17 21:21:28

ByVal 创建变量的副本,而 ByRef 传递指针。 因此,我想说 ByVal 速度较慢(由于复制需要时间)并且使用更多内存。

ByVal creates a copy of the variable, whereas ByRef passes a pointer. I would therefore say that ByVal is slower (due to time it takes to copy) and uses more memory.

半步萧音过轻尘 2024-07-17 21:21:28

我的好奇心是检查取决于对象和内存使用情况的不同行为

结果似乎表明 ByVal 总是获胜,资源取决于是否收集内存或更少(仅限 4.5.1)

Public Structure rStruct
    Public v1 As Integer
    Public v2 As String
End Structure

Public Class tClass
    Public v1 As Integer
    Public v2 As String
End Class



Public Sub Method1(ByRef s As String)
    Dim c As String = s
End Sub

Public Sub Method2(ByVal s As String)
    Dim c As String = s
End Sub

Public Sub Method3(ByRef i As Integer)
    Dim x As Integer = i
End Sub

Public Sub Method4(ByVal i As Integer)
    Dim x As Integer = i
End Sub

Public Sub Method5(ByVal st As rStruct)
    Dim x As rStruct = st
End Sub

Public Sub Method6(ByRef st As rStruct)
    Dim x As rStruct = st
End Sub


Public Sub Method7(ByVal cs As tClass)
    Dim x As tClass = cs
End Sub

Public Sub Method8(ByRef cs As tClass)
    Dim x As tClass = cs
End Sub
Sub DoTest()

    Dim s As String = "Hello World!"
    Dim cs As New tClass
    cs.v1 = 1
    cs.v2 = s
    Dim rt As New rStruct
    rt.v1 = 1
    rt.v2 = s
    Dim k As Integer = 5




    ListBox1.Items.Add("BEGIN")

    Dim t As New Stopwatch
    Dim gt As New Stopwatch

    If CheckBox1.Checked Then
        ListBox1.Items.Add("Using Garbage Collection")
        System.Runtime.GCSettings.LargeObjectHeapCompactionMode = System.Runtime.GCLargeObjectHeapCompactionMode.CompactOnce
        GC.Collect()
        GC.WaitForPendingFinalizers()
        GC.Collect()
        GC.GetTotalMemory(False)
    End If

    Dim d As Double = GC.GetTotalMemory(False)

    ListBox1.Items.Add("Free Memory:   " & d)

    gt.Start()
    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method1(s)
    Next
    t.Stop()

    ListBox1.Items.Add("Reference Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method2(s)
    Next
    t.Stop()

    ListBox1.Items.Add("Reference Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method3(i)
    Next
    t.Stop()

    ListBox1.Items.Add("Value Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method4(i)
    Next
    t.Stop()

    ListBox1.Items.Add("Value Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method5(rt)
    Next
    t.Stop()

    ListBox1.Items.Add("Structure Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method6(rt)
    Next
    t.Stop()

    ListBox1.Items.Add("Structure Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method7(cs)
    Next
    t.Stop()

    ListBox1.Items.Add("Class Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method8(cs)
    Next
    t.Stop()
    gt.Stop()

    ListBox1.Items.Add("Class Type - ByRef " & t.ElapsedMilliseconds)
    ListBox1.Items.Add("Total time " & gt.ElapsedMilliseconds)
    d = GC.GetTotalMemory(True) - d
    ListBox1.Items.Add("Total Memory Heap consuming (bytes)" & d)


    ListBox1.Items.Add("END")

End Sub


Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click


    DoTest()

End Sub

My curiosity was to check the different behaviours depending object and memory usages

The result seems demostrate that ByVal always wins, the resource depends if collect memory or less (4.5.1 only)

Public Structure rStruct
    Public v1 As Integer
    Public v2 As String
End Structure

Public Class tClass
    Public v1 As Integer
    Public v2 As String
End Class



Public Sub Method1(ByRef s As String)
    Dim c As String = s
End Sub

Public Sub Method2(ByVal s As String)
    Dim c As String = s
End Sub

Public Sub Method3(ByRef i As Integer)
    Dim x As Integer = i
End Sub

Public Sub Method4(ByVal i As Integer)
    Dim x As Integer = i
End Sub

Public Sub Method5(ByVal st As rStruct)
    Dim x As rStruct = st
End Sub

Public Sub Method6(ByRef st As rStruct)
    Dim x As rStruct = st
End Sub


Public Sub Method7(ByVal cs As tClass)
    Dim x As tClass = cs
End Sub

Public Sub Method8(ByRef cs As tClass)
    Dim x As tClass = cs
End Sub
Sub DoTest()

    Dim s As String = "Hello World!"
    Dim cs As New tClass
    cs.v1 = 1
    cs.v2 = s
    Dim rt As New rStruct
    rt.v1 = 1
    rt.v2 = s
    Dim k As Integer = 5




    ListBox1.Items.Add("BEGIN")

    Dim t As New Stopwatch
    Dim gt As New Stopwatch

    If CheckBox1.Checked Then
        ListBox1.Items.Add("Using Garbage Collection")
        System.Runtime.GCSettings.LargeObjectHeapCompactionMode = System.Runtime.GCLargeObjectHeapCompactionMode.CompactOnce
        GC.Collect()
        GC.WaitForPendingFinalizers()
        GC.Collect()
        GC.GetTotalMemory(False)
    End If

    Dim d As Double = GC.GetTotalMemory(False)

    ListBox1.Items.Add("Free Memory:   " & d)

    gt.Start()
    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method1(s)
    Next
    t.Stop()

    ListBox1.Items.Add("Reference Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method2(s)
    Next
    t.Stop()

    ListBox1.Items.Add("Reference Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method3(i)
    Next
    t.Stop()

    ListBox1.Items.Add("Value Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method4(i)
    Next
    t.Stop()

    ListBox1.Items.Add("Value Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method5(rt)
    Next
    t.Stop()

    ListBox1.Items.Add("Structure Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method6(rt)
    Next
    t.Stop()

    ListBox1.Items.Add("Structure Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method7(cs)
    Next
    t.Stop()

    ListBox1.Items.Add("Class Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method8(cs)
    Next
    t.Stop()
    gt.Stop()

    ListBox1.Items.Add("Class Type - ByRef " & t.ElapsedMilliseconds)
    ListBox1.Items.Add("Total time " & gt.ElapsedMilliseconds)
    d = GC.GetTotalMemory(True) - d
    ListBox1.Items.Add("Total Memory Heap consuming (bytes)" & d)


    ListBox1.Items.Add("END")

End Sub


Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click


    DoTest()

End Sub
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文