这里的这个图解是不是有问题
let t: (i32, String) = (5, “Hello”.to_string);
let mut b = Box::new(t);
t在内存中还能转移的?t在栈上,被Box包了,就变到了堆上了?
我感觉应该是这样的
有什么办法可以验证
1
共 11 条评论, 1 页
这里的这个图解是不是有问题
let t: (i32, String) = (5, “Hello”.to_string);
let mut b = Box::new(t);
t在内存中还能转移的?t在栈上,被Box包了,就变到了堆上了?
我感觉应该是这样的
有什么办法可以验证
评论区
写评论看一下汇编就好了
逐段分析
保存现场,访问了一个GOT表的地址,不清楚作用
堆分配一个5字节,1字节对齐的空间
错误处理,忽略
保存rax指针,即字符串数据指针,做字符串赋值,111对应'o',那串数字转16进制的每个字节就是对应“Hell"
分配一个32字节的空间,给box元组使用
元组赋值,编译器优化后2不放置在栈上,直接移动到堆上了,字符串也是直接在堆上创建了,不需要再搬一次
传入Box::new函数copy一份栈上的数据到堆上不是很正常吗?
t不能用了,如果要想t还可能用,需要
let mut b = Box::new(t.clone());
这样就懂了,这里其实就是转移了,本质是 copy trait吧,其实也就是数据从栈上转移到堆上了--
👇
cybertheye: 那t还是t是吧
--
👇
ggggjlgl: 转移应该是move语义,move会使b拥有原属t的元组并且要求编译器将t视作未初始化状态(但可能为了效率,好像并没有重置t的内存)。
只是Box这个智能指针会强制将数据分配在堆上,所以应该是发生了对t拥有的元组的隐式浅拷贝,Rust不会隐式拷贝复杂数据,这里应该是拷贝了i32、ptr_str、cap、len这几个机器字。
所以是发生了数据拷贝
--
👇
Bai-Jinlin: 写成c可能就好理解了
那t还是t是吧
--
👇
ggggjlgl: 转移应该是move语义,move会使b拥有原属t的元组并且要求编译器将t视作未初始化状态(但可能为了效率,好像并没有重置t的内存)。
只是Box这个智能指针会强制将数据分配在堆上,所以应该是发生了对t拥有的元组的隐式浅拷贝,Rust不会隐式拷贝复杂数据,这里应该是拷贝了i32、ptr_str、cap、len这几个机器字。
元组好像是在栈上吧
--
👇
ggggjlgl: 等大神回复下怎么验证。 还有t声明语句执行完之后,这个元组被分配在栈上还是堆上,我一直觉得这种简单数据会在栈上,但是看完内存现在觉得这个元组一开始就在堆上。
写成c可能就好理解了
Box类型的注释: A pointer type that uniquely owns a heap allocation of type
T
.Box::new()的注释: Allocates memory on the heap and then places
x
into it.毫无疑问Box的内容是存在堆上的,栈上的只是指针。
至于Box::new()是怎么拷贝过去的,我不清楚
等大神回复下怎么验证。 还有t声明语句执行完之后,这个元组被分配在栈上还是堆上,我一直觉得这种简单数据会在栈上,但是看完内存现在觉得这个元组一开始就在堆上。
转移应该是move语义,move会使b拥有原属t的元组并且要求编译器将t视作未初始化状态(但可能为了效率,好像并没有重置t的内存)。
只是Box这个智能指针会强制将数据分配在堆上,所以应该是发生了对t拥有的元组的隐式浅拷贝,Rust不会隐式拷贝复杂数据,这里应该是拷贝了i32、ptr_str、cap、len这几个机器字。
移动语义和堆栈没啥关系,不要搞混了