结构体内存分配机制|学习笔记

简介: 快速学习结构体内存分配机制

开发者学堂课程【Go 语言核心编程 - 面向对象、文件、单元测试、反射、TCP 编程:结构体内存分配机制】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/626/detail/9738


结构体内存分配机制


内容介绍:

一、结构体内存分配机制中的问题一

二、结构体内存分配机制中的问题二

三、结构体内存分配机制中的问题三

 

一、结构体内存分配机制中的问题一

我们定义一个Person结构体(包括名字,年龄)。

我们看看下面一段代码,输出什么内容?

var p1 Person

p1.Age=10

p1.Name="小明"

var p2 Person = p1

fmt.PrintIn(p2.Age)

p2.Name = "tom"

fmt.Printf("p2.Name=%v p1.Name=%v", p2.Name, p1.Name)

l 输出的结果是p1:小明、p2:Tom

1、问题分析

定义了一个person结构体变量,age字段赋值为10,Name字段赋值为小明,然后把p1交给p2,上述过程执行的时候,p1会指向一个数据空间,空间里会有名字:小明,还有一个年龄:十岁。当我们把p1交给p2的时候,进行值的拷贝,由于结构体这种数据类型默认值是拷贝的,因此p2也会有一个数据空间,p2会指向自己的数据空间,将小明还有其年龄拷贝过去。输出(p2.Age)结果为10。通过p2的结构体变量访问到它的属性,将小明改成tom,而这样的修改不会影响到p1。输出p2与p1的Name分别是 tom 和小明。

2、基本说明

变量总是存在内存中的,那么结构体变量在内存中究竟是怎样存在的?

image.png

结构体在内存中的示意图

对图示进行分析:例如写入两个人,一个是小明,一个是tom,当我们把p1交给p2的时候,会进行一次值拷贝,且他们之间的数据空间是完全独立的。

 

二、结构体内存分配机制中的问题二

下面一段代码,会输出什么信息:

var p1 Person

p1.Age=10

p1.Name= "小明"

var p2*Person = &p1

fmt.Println((*p2).Age)

fmt.Println(p2.Age)

p2.Name = "tom~"

fmt.Printf("p2.Name=%v p1.Name=%v \n",p2.Name, p1.Name)

fmt.Printf("p2.Name=%v p1.Name=%v \n",(*p2).Name, p1.Name)

l 输出结果为:p1、p2均为tom~

1、问题分析

创建p1结构体变量,为其年龄名字赋值,把p1变量的地址交给了p2,而p2是一个结构体指针。利用取值符,把Age取出,值为10,然后把p2的年龄也进行输出。p2是一个指针,它指向p1,所以p2的年龄也是10。通过p2修改名字,把它改成Tom。进入到chapter10,然后cd到刚才的exercise,go run main.go,运行起来,完成p2和p1Name输出,因为此刻是指针,所以此时p1和p2 Name都应该是tom~若以(*.p2).Name的形式输出则输出结果为

p2.Name=tom~ p1.Name =tom~

p1的地址0xc0420023e0 p2的地址0xc042004028 p2的值0xc0420023e0

测试程序

核心代码:

package main

import(

"fmt"

)

type Person struct{

Name string

Age int

}

func main(){

var p1 Person

p1.Age=10

p1.Name=“小明”

var p2 *Person = &p1//这里是关键-->将画出示意图

fmt.Print1n((*p2).Age)

fmt.Print1n(p2.Age)

p2.Name = "tom~"

fmt.Printf("p2.Name=%v p1.Name=%v \n", p2.Name,p1.Name)

fmt.Printf("p2.Name=%v p1.Name=%v \n",(*p2).Name,p1.Name)

}

2、示意图

image.png

结构体在内存中的示意图

对示意图进行分析:创建一个p1,内存里p1这个变量就会分配一个空间。

p1里面有两个字段,Name和Age,Name值给成小明,年龄给成10,p1就这样指向了其空间。关键代码表示把p1的地址交给了指针p2, 这时会有一个新的p2指向一个空间,但这个空间里面存的是p1结构体的地址,而p1结构体的地址可以通过fmt.Printf("p1的地址%p\n",&p1)进行查看,这个地址会指向p1结构体的空间。p2本身的地址可以通过fmt.Printf("p2的地址%p\n",&p)进行查看,同时可对刚才的结果通过fmt.Printf("p2的值%p\n",&p)进行判断,应恰好等于p1的地址,即可证明了p2指针的存放地址指向p1结构体的数据空间。通过p1的地址找到了其数据空间,再找到Age,打印出10,同样p2.Name打印出小明。这句话之所以可以这么用,是因为go的设计者做了简化处理,为了大家使用方便,支持指针直接去访问它的字段。p2.name=tom,其实是通过指针的地址找到了它指向的数据空间,然后找到里面的Name字段,然后将值改成了tom~。通过p2去改变内容,p1就会发生变化,这是因为他们共享一份数据空间,所以最终访问结果都是tom~,同样的道理用(*p2)去访问,最终结果也是tom~

 

三、结构体内存分配机制中的问题三

看下面代码,并分析原因

var p1 Person

p1.Age=10

p1.Name= "小明”

var p2*Person = &p1

fmt.PrintIn(*p2.Age)//能不能这样写?

结果为:不能按题目所写

问题分析

为结构体p1的两个字段赋值,然后把p1的地址交给p2指针,题目中fmt.Println(*p2.Age)与原先所写的唯一的区别就是没有把*p2用括号括起来,而这样做是不对的,这是因为.的运算优先级*高。

相关文章
|
6月前
|
安全 程序员 C++
C++中的智能指针:从原始指针到现代内存管理
C++中的智能指针:从原始指针到现代内存管理
48 0
|
存储 缓存 算法
内存分配不再神秘:深入剖析malloc函数实现原理与机制
内存分配不再神秘:深入剖析malloc函数实现原理与机制
|
存储 编译器 C语言
深入理解C++内存管理:指针、引用和内存分配(下)
深入理解C++内存管理:指针、引用和内存分配
|
6月前
|
存储 算法 大数据
内存原理 | 内存分配 | 内存对齐
内存原理 | 内存分配 | 内存对齐
|
程序员 编译器 C语言
动态内存管理函数的使用与优化技巧(内存函数、柔性数组)(上)
动态内存管理函数的使用与优化技巧(内存函数、柔性数组)(上)
75 0
|
程序员 C语言 C++
动态内存管理函数的使用与优化技巧(内存函数、柔性数组)(下)
动态内存管理函数的使用与优化技巧(内存函数、柔性数组)(下)
52 0
|
4天前
|
存储 缓存 算法
结构体和类在内存管理方面有哪些具体差异?
【10月更文挑战第30天】结构体和类在内存管理方面的差异决定了它们在不同的应用场景下各有优劣。在实际编程中,需要根据具体的需求和性能要求来合理选择使用结构体还是类。
|
22天前
|
Java 程序员 编译器
内存分配的基本概念
【10月更文挑战第10天】
28 4
|
6月前
|
存储
内存管理之内存释放函数
内存管理之内存释放函数
72 0
|
6月前
|
存储 程序员 C语言
内存管理——内存分配函数
内存管理——内存分配函数
50 0