bitmap的奇怪赋值方式

6lilu9 2017-11-04 05:50:18
一、
毫无疑问,肯定弹出的对话框是2 ,即后面a的变化不会影响b的值了。
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim a, b As Integer
a = 2
b = a
a = 3
MsgBox(b)
End Sub



二、那大家猜猜,这段代码运行后,picturebox2的图像中会出现一道线还是两道线呢?
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim BMP1, BMP2 As New Bitmap(255, 208)

Dim G1 As Graphics = Graphics.FromImage(BMP1)
G1.DrawLine(New Pen(Color.Black, 3), 0, 0, 200, 200)


BMP2 = BMP1
Me.PictureBox2.Image = BMP2

G1.DrawLine(New Pen(Color.Red, 3), 0, 200, 200, 0)
Me.PictureBox1.Image = BMP1
End Sub



三、那大家猜猜,这段代码运行后,picturebox2的图像中会出现一道线还是两道线呢?
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim BMP1, BMP2 As New Bitmap(255, 208)

Dim G1 As Graphics = Graphics.FromImage(BMP1)
G1.DrawLine(New Pen(Color.Black, 3), 0, 0, 200, 200)
G1.DrawLine(New Pen(Color.Red, 3), 0, 200, 200, 0)
Me.PictureBox1.Image = BMP1

BMP2 = BMP1
Me.PictureBox2.Image = BMP2

End Sub


四、我想达到picturebox2中只出现一条线的结果,请高手解疑(我总觉得 我的知识体系中缺少了好多内容)
...全文
456 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
lilunlil 2017-11-25
  • 打赏
  • 举报
回复
直接告诉你干货。 将图片转成二进制数组储存起来,然后第二张图片再从数组转过来。
6lilu9 2017-11-25
  • 打赏
  • 举报
回复
引用 8 楼 zcsor 的回复:
框架会对类型进行检查,以便按照约定好的值类型或引用型的传递方式来传递内容,所以有一些你看不到的信息保证了这些的正确进行。就问题本身来看就是赋值运算符的应用,对于值类型,就是传值,你明白了是正确的;对于引用型就是传址,你明白的也是正确的。只是中间编译器、运行时它们会做一些检查以保证不会发生那些“浪费了程序员精力”的内存使用问题。要理解这些东西,可以有很多途径,例如可以看看”值类型与引用类型”,“装箱和拆箱”,“元数据”等一些内容,不仅可以解决当前的问题,也能明白泛型之类的东西。手头有一些x32dbg,x64dbg啥的也可以尝试去看看内存里面的东西,写一个简单的小程序测试一下你的dim a,b as integer部分,通过跟踪可以看到栈里面a,b的变化;对于引用型可以利用委托,委托是一种引用型,可以跟踪它在赋值过程中堆的变化。 就代码说,你这个BMP1和BMP2开始是两个对象A,B来的,后来你把BMP2指向了BMP1,所以它俩就都是A了,原来那个B被GC干掉了。而你的画布只有一个,是BMP1的。如果说从内存地址理解,BMP实际上就是一个数组(可以参考一下lockbit方法的相关内容),开始BMP1里面是数组A起地址,BMP2里面是数组B起地址,后来你给BMP2也换成A的起地址了。这是两个问题。 再者,picbox的image属性它会被picbox控件自动重绘的,可以用工具反编译一下这个控件的实现看一看。当你改变它所指向的bitmap,那它自然体现出来。借用一段你的代码,并稍微修改一下:         Dim BMP1, BMP2 As New Bitmap(255, 208)       Dim G1 As Graphics = Graphics.FromImage(BMP1) Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click          G1.DrawLine(New Pen(Color.Black, 3), 0, 0, 200, 200)         Me.PictureBox1.Image = BMP1     End Sub   Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click         BMP2 = BMP1          G1.DrawLine(New Pen(Color.Red, 3), 0, 200, 200, 0)         Me.PictureBox2.Image = BMP2     End Sub  你猜猜会有几条线? 这是程序设计思路问题,如果你要动态的显示图片,并且在一张图上不断修改,那么就用一张图,用paint事件。如果你要用多个图,那你就用多个bitmap,并且每一个都有自己的graphics,都有自己单独的函数去操作,而后在click事件调用这些函数,如果代码重复,那么把对象参数化进行传递形成一个函数或过程。不管怎么样,首先,保持你的思路清晰,别上来自己先糊了;首后,保证一个相对规范的代码习惯。
谢谢,受教很多,真想打赏给你。 这实在是一篇最有价值的回复,既肯定了我知道的一些内容,又指出了我应该思考的思路。 再次感谢。
清晨曦月 元老 2017-11-22
  • 打赏
  • 举报
回复
框架会对类型进行检查,以便按照约定好的值类型或引用型的传递方式来传递内容,所以有一些你看不到的信息保证了这些的正确进行。就问题本身来看就是赋值运算符的应用,对于值类型,就是传值,你明白了是正确的;对于引用型就是传址,你明白的也是正确的。只是中间编译器、运行时它们会做一些检查以保证不会发生那些“浪费了程序员精力”的内存使用问题。要理解这些东西,可以有很多途径,例如可以看看”值类型与引用类型”,“装箱和拆箱”,“元数据”等一些内容,不仅可以解决当前的问题,也能明白泛型之类的东西。手头有一些x32dbg,x64dbg啥的也可以尝试去看看内存里面的东西,写一个简单的小程序测试一下你的dim a,b as integer部分,通过跟踪可以看到栈里面a,b的变化;对于引用型可以利用委托,委托是一种引用型,可以跟踪它在赋值过程中堆的变化。 就代码说,你这个BMP1和BMP2开始是两个对象A,B来的,后来你把BMP2指向了BMP1,所以它俩就都是A了,原来那个B被GC干掉了。而你的画布只有一个,是BMP1的。如果说从内存地址理解,BMP实际上就是一个数组(可以参考一下lockbit方法的相关内容),开始BMP1里面是数组A起地址,BMP2里面是数组B起地址,后来你给BMP2也换成A的起地址了。这是两个问题。 再者,picbox的image属性它会被picbox控件自动重绘的,可以用工具反编译一下这个控件的实现看一看。当你改变它所指向的bitmap,那它自然体现出来。借用一段你的代码,并稍微修改一下:         Dim BMP1, BMP2 As New Bitmap(255, 208)       Dim G1 As Graphics = Graphics.FromImage(BMP1) Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click          G1.DrawLine(New Pen(Color.Black, 3), 0, 0, 200, 200)         Me.PictureBox1.Image = BMP1     End Sub   Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click         BMP2 = BMP1          G1.DrawLine(New Pen(Color.Red, 3), 0, 200, 200, 0)         Me.PictureBox2.Image = BMP2     End Sub  你猜猜会有几条线? 这是程序设计思路问题,如果你要动态的显示图片,并且在一张图上不断修改,那么就用一张图,用paint事件。如果你要用多个图,那你就用多个bitmap,并且每一个都有自己的graphics,都有自己单独的函数去操作,而后在click事件调用这些函数,如果代码重复,那么把对象参数化进行传递形成一个函数或过程。不管怎么样,首先,保持你的思路清晰,别上来自己先糊了;首后,保证一个相对规范的代码习惯。
VB.Net 2017-11-05
  • 打赏
  • 举报
回复
引用 3 楼 lengyeshuang 的回复:
[quote=引用 2 楼 UruseiBest 的回复:] [quote=引用 1 楼 UruseiBest 的回复:] Bitmap 应该是传址的。
额,说法不准确 BMP2 = BMP1 应该是Bmp2引用了Bmp1[/quote] 当我看到”传址“时,我以为我懂了; 后来看到你纠正成”引用“,我又彻底蒙了; 但我既不是搞科研的,我现在就想明白怎么才能达到我想要的结果呢? 非常感谢[/quote] 分开写吧
  • 打赏
  • 举报
回复
c语言所谓“传址”,其实是非常底层的、无原则地。比如说你可以把一个字符的地址去覆盖给一个设备的地址,可以胡乱传址,而几乎无法由系统程序来自动发现野地址。而.net完全是规范的、托管的,所以叫做引用。
  • 打赏
  • 举报
回复
引用 3 楼 lengyeshuang 的回复:
当我看到”传址“时,我以为我懂了; 后来看到你纠正成”引用“,我又彻底蒙了; 但我既不是搞科研的,我现在就想明白怎么才能达到我想要的结果呢? 非常感谢
在 .net 托管代码程序设计中并没有什么“地址”概念,它的引用机制更加复杂,在运行中有着复杂的处理过程。但是对于使用基本的引用类型变量,你可以把“传址”当作一种很好的“比喻”,用比喻来理解是可以接近真相的(但是要知道比喻永远都有被修改的那一天)。所以引用类型的赋值就可以被看作是为是“地址”的赋值而不是对象本身的赋值。 至于说“怎么打到我想要的结果”,其实这完全在于自己的悟性。自己越对原理理解得多,就越能自己设计出正确的程序。靠自己。
  • 打赏
  • 举报
回复
BMP2=BMP1,这样的结果是 BMP2 和 BMP1 引用同一个对象;而 b=a 的结果,此时 b 和 a 并不引用同一个对象,因为值类型变量的赋值操作总是产生新的对象。
6lilu9 2017-11-05
  • 打赏
  • 举报
回复
引用 2 楼 UruseiBest 的回复:
[quote=引用 1 楼 UruseiBest 的回复:] Bitmap 应该是传址的。
额,说法不准确 BMP2 = BMP1 应该是Bmp2引用了Bmp1[/quote] 当我看到”传址“时,我以为我懂了; 后来看到你纠正成”引用“,我又彻底蒙了; 但我既不是搞科研的,我现在就想明白怎么才能达到我想要的结果呢? 非常感谢
VB.Net 2017-11-04
  • 打赏
  • 举报
回复
引用 1 楼 UruseiBest 的回复:
Bitmap 应该是传址的。
额,说法不准确 BMP2 = BMP1 应该是Bmp2引用了Bmp1
VB.Net 2017-11-04
  • 打赏
  • 举报
回复
Bitmap 应该是传址的。

16,553

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧