Apa yang berlaku di sebalik tabir struktur ini? Adakah struct akan disalin?

PHPz
Lepaskan: 2024-02-05 23:27:03
ke hadapan
819 orang telah melayarinya

这些结构的幕后发生了什么? struct 会被复制吗?

Kandungan soalan

Saya tidak faham apa yang berlaku dalam kod ini.

Fungsi penerima berfungsi pada pengguna struktur asal (kerana penunjuk), jadi di dalam func kami menukar obj asal. Tetapi adakah alamat struktur juga asal atau salinan asal "a"?

func main() {
    a := address{"freedom", "kyiv"}
    u := user{"valeriy", "zalyzhnyi", a}
    fmt.println(a)
    fmt.println(u)
    u.updatestreet("peremohy")

    fmt.println(a)
    fmt.println(u)
}

func (u *user) updatestreet(street string) {
    u.address.street = street
}

type user struct {
    firstname string
    lastname  string
    address   address
}

type address struct {
    street string
    city   string
}
Salin selepas log masuk

Ini hasil keluaran saya

{Freedom Kyiv}
{Valeriy Zalyzhnyi {Freedom Kyiv}}
{Freedom Kyiv}
{Valeriy Zalyzhnyi {Peremohy Kyiv}}
Salin selepas log masuk

Daripada ini saya faham bahawa alamat u telah berubah, dan saya juga melihat bahawa "a" di dalam "u" adalah berbeza daripada obj asal. Jadi apa sebenarnya yang berlaku di sebalik tabir dan dalam ingatan? Berdasarkan output, tingkah laku ini benar-benar tidak dijangka kepada saya. Saya menjangkakan bahawa disebabkan kehadiran penunjuk kami menggunakan objek asal ("a" dan "u") dalam kedua-dua kes. Kali kedua (selepas func 'kemas kini..') mencetak fmt.println(a) akan memberi kami {peremohy kyiv}, kerana kali kedua fmt.println(u) memberi kami {valeriy zalyzhnyi {peremohy kyiv}}


Jawapan Betul


Untuk memahami perkara yang berlaku di sebalik tabir , adalah berguna untuk menggambarkan perkara yang dilakukan oleh kod:

a = address{}
u := user{address: a}
Salin selepas log masuk

terbahagi kepada:

| variable value        | memory address |
| a = address{}         | 0x000001       |
| u = user{}            | 0x000002       |
| u.address = copy of a | 0x000003       |
Salin selepas log masuk

Jadi anda telah memperuntukkan memori untuk 1 user{} 实例和 2 个 address{} contoh. Nilai contoh alamat kedua ialah salinan tepat contoh alamat pertama (pada masa salinan dibuat).

Sekarang, apabila anda memanggil updatestreet 时,它是通过指针在 u 上调用的,它不会创建 user 实例的副本,而是对内存地址 0x000002 进行操作,因此它实际上对同一个 a pembolehubah beroperasi. Oleh itu ungkapan:

u.address.street = "foo"
Salin selepas log masuk

diterjemahkan kepada: Pada nilai yang dipegang pada alamat memori 0x000002, akses nilai bernama address 的字段,在该字段中,访问字段 street dan tetapkan nilai baharu. Mari petakan ini pada jadual yang kami buat di atas:

0x000002 -> address (which is stored in 0x000003)
              |
              --> set street to "foo"
Salin selepas log masuk
Selepas fungsi

kembali, kita masih mempunyai objek yang sama di lokasi yang sama dalam ingatan seperti sebelumnya, tetapi kerana kita mengakses nilai a 的值,所以 updatestreet 函数所做的更改已经完成为 u melalui alamat dalam ingatan (kerana kita menggunakan alamat memori yang sama).

Fungsi a 在赋值给 u.address 时被复制,因此它的内存地址未知,或者传递给 updatestreet Boleh ubah dan oleh itu kekal tidak berubah.

Atas ialah kandungan terperinci Apa yang berlaku di sebalik tabir struktur ini? Adakah struct akan disalin?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!