LINUX.ORG.RU

как rust захватывает ссылки

 


1

5

Предположим, есть такой код

fn f(x : Box<i32>) -> Box<i32> {
	if some_random_value {
		return x;
	} else {
		return Box::new(10);
	}
}


fn g() -> Box<i32> {
	let x = Box::new(20);
	return f(x);	
}

fn main() {
	let a = g();
}

Как раст понимает, что после вызова g() память, выделенную под Box::new(20), надо освободить? Ведь, насколько я понимаю, в зависимости от случайного события (some_random_value) Box::new(20) надо либо удалить после g(), либо вернуть как результат


Вообще-то ты «передаёшь по значению» Box, то есть перемещаешь его. Соответственно g вообще не отвечает за освобождение памяти. И ссылок тут нет.

DarkEld3r ★★★★★
()
Последнее исправление: DarkEld3r (всего исправлений: 1)

При вызове f(x) забирает владение x себе. g за него больше не отвечает, можно считать, что x после вызова f(x) не определена.

Внутри f если выполнение пошло в первую ветку, x возвращается и владеть им будет тот, кто вызывал f. Т.е. владельцем станет на какой-то момент g, но она сразу же вернёт это значение в main и владельцем 20-ки станет main. После выхода из main это значение удалится.

Если выполнение пошло во вторую ветку, то возвращается новое значение 10. При этом f владеет переменной x и, соответственно, удаляет её. Дальше всё происходит как в первом варианте и в конце концов main удалит 10.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)

Псевдокод-аналог на C:

int *f(int* x) {
  if some_random_value {
    return x;
  } else {
    free(x);
    return malloc_int(10);
  }
}

int *g(void) {
  int *x = malloc_int(20);
  return f(x);
}

void main(void) {
  int *a = g();
  free(a);
}

Legioner ★★★★★
()

Хватит совать return во все места, это же не си.

loyd
()

Для Box реализован Drop. Для того, чтобы лучше понять, как работает отслеживание принадлежности, можно реализовать Drop для своей структуры и поэкспериментировать, как показано здесь и здесь.

Anatolik ★★
()
Последнее исправление: Anatolik (всего исправлений: 1)

всем спасибо за ответы!

jcdr
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.