将字符串作为参数传递给函数时,时间复杂度有何不同?

What is the difference in time complexity when passing a string versus a pointer to the string as parameter to a function?

假设我有一个字符串 s。

 s := "helloworld"

现在,我的问题是,如果 s 有 'n' 个字节,如果我将 s 传递给一个函数与如果我将 &s 传递给一个函数并且 'n' 的时间复杂度是多少然后访问字符串的第 i 个字节。

如果我将 &s 传递给函数并访问字符串的第 i 个字节需要 O(1) 时间,那么当我将 s 传递给函数然后访问第 i 个字节是否需要 O(n) 时间字符串的字节(因为整个字符串将被复制)?

我试过了,发现复制一个字符串确实会改变指向它的指针。希望对此更加清楚。

func main() {
    str := "helloworld"
    fmt.Println("string pointer 1:", &str)
    printStringPointer(str)
}

func printStringPointer(s string) {
    fmt.Println("string pointer 2:", &s)
}

输出:

string pointer 1: 0xc000010200
string pointer 2: 0xc000010210

go 中的字符串类似于切片,它们只是一个包含指向底层数据的指针和长度的薄描述符。

您可以在 reflect.StringHeader 类型中看到:

type StringHeader struct {
    Data uintptr
    Len  int
}

将字符串传递给函数时,会复制 header,但不会复制基础数据。我们可以更改您的示例以打印 Data 的值,表明它指向内存中的相同地址:playground link:

func main() {
    str := "helloworld"
    fmt.Println("string pointer 1: ", &str)
    fmt.Println("string Data 1:    ", (*reflect.StringHeader)(unsafe.Pointer(&str)).Data)
    printStringPointer(str)
}

func printStringPointer(s string) {
    fmt.Println("string pointer 2: ", &s)
    fmt.Println("string Data 2:    ", (*reflect.StringHeader)(unsafe.Pointer(&s)).Data)
}

输出:

string pointer 1:  0xc000010200
string Data 1:     4970654
string pointer 2:  0xc000010210
string Data 2:     4970654

传递字符串是常数时间(复制header),不复制底层数据.