Действительно ли возвращение указателя на структуру из функции на самом деле означает передачу владения указателем на кучу?

Можно ли сказать, что функция `give_str()` со синтаксическим сахаром возвращает указатель на строку, а вызывающей стороне нужно самой управлять памятью, в то время как без синтаксического сахара функция `give_str()` возвращает умный указатель `Box` на строку, который автоматически управляет памятью? Будут ли эти две функции создавать одинаковый ассемблерный код? В частности, нет ли волшебной операции, которая отбрасывает владение указателем?
  • 28 сентября 2023 г. 12:57
Ответы на вопрос 2
Возвращение указателя на структуру из функции не обязательно означает передачу владения указателем на кучу. Это зависит от специфики функции и ее цели.

Функция `give_str()` может вернуть указатель на строку, но это не обязательно означает, что вызывающей стороне нужно самой управлять памятью. Если функция создает строку на куче и возвращает указатель на нее, то вызывающей стороне придется самой освобождать память после использования этой строки. Однако, если функция `give_str()` использует умный указатель `Box`, то управление памятью будет автоматически обеспечиваться этим указателем.

Точный ассемблерный код, генерируемый для этих двух функций, может отличаться в зависимости от контекста и компилятора. Однако, в общем случае, функция `give_str()` без синтаксического сахара должна создавать экземпляр `Box` для управления памятью указателем на строку, тогда как функция `give_str()` с синтаксическим сахаром может просто возвращать указатель на строку без использования умных указателей.

Во втором вопросе нет волшебной операции, которая отбрасывает владение указателем. Вероятно, вы имели в виду операцию, которая передает владение указателем другому объекту, например, при присваивании или передаче в качестве аргумента функции. Необходимо явно указать, что владение указателем передается, например, путем вызова функции `into_raw()` для умного указателя `Box` или использования метода `forget()` для указателя на структуру.
Нет, эти два примера кода делают разные вещи. В первом случае возвращается `String`, содержащий несколько полей: `len`, `capacity` и указатель на буфер. Во втором случае `String` копируется в кучу, а возвращается указатель на `String` в куче. Это можно увидеть, обратившись к ассемблерному коду.

Первая функция:
```
pushq	%rbx
movq	%rdi, %rbx
movq	__rust_no_alloc_shim_is_unstable@GOTPCREL(%rip), %rax
movzbl	(%rax), %eax
movl	$5, %edi
movl	$1, %esi
callq	*__rust_alloc@GOTPCREL(%rip)
testq	%rax, %rax
je	.LBB10_1
movb	$114, 4(%rax)
movl	$1701736041, (%rax)
movq	%rax, (%rbx)
movq	$5, 8(%rbx)
movq	$5, 16(%rbx)
popq	%rbx
retq
```

Вторая функция:
```
pushq	%r14
pushq	%rbx
pushq	%rax
movq	__rust_no_alloc_shim_is_unstable@GOTPCREL(%rip), %r14
movzbl	(%r14), %eax
movl	$5, %edi
movl	$1, %esi
callq	*__rust_alloc@GOTPCREL(%rip)
testq	%rax, %rax
je	.LBB11_6
movq	%rax, %rbx
movb	$114, 4(%rax)
movl	$1701736041, (%rax)
movzbl	(%r14), %eax
movl	$24, %edi
movl	$8, %esi
callq	*__rust_alloc@GOTPCREL(%rip)
testq	%rax, %rax
je	.LBB11_2
movq	%rbx, (%rax)
movq	$5, 8(%rax)
movq	$5, 16(%rax)
addq	$8, %rsp
popq	%rbx
popq	%r14
retq
```
Похожие вопросы