Rust автоматически оборачивает все данные, возвращенные функцией в Box? - PullRequest
0 голосов
/ 09 февраля 2020

Давайте рассмотрим этот пример:

fn hello() -> String {
    String::from("Hello")
}

Эквивалентным примером в C будет использование mallo c, запись символов в память и возврат указателя. Почему работает код Rust? Почему бы мне не написать это так:

fn hello() -> Box<String> {
    Box::from(String::from("Hello"))
}

Чтобы создать значение внутри функции и позволить этой функции вернуть его, значение всегда должно создаваться в куче, а не в стеке, это точно. Почему Rust использует синтаксис, который на первый взгляд указывает, что вы можете возвращать переменные стека?

Руст автоматически упаковывает все данные, возвращаемые функцией в Box? Или есть какие-то другие маги Rust c?

Я предполагаю, что это синтаксис c сахар, чтобы не заставлять переносить возвращаемые значения в Box.

Мой вопрос не ограничивается строками; речь идет о возвращении структур из функций в целом. Я знаю, что основной вектор хранит свои данные в куче. Этот вопрос касается только метаданных структуры (т. Е. Указателей на данные в куче) и того, как они возвращаются (при выводе компилятором), когда функция возвращает.

Ответы [ 3 ]

4 голосов
/ 09 февраля 2020

Нет.

Руст ничего от вас не скрывает.

Если вы напишите, что возвращаете String, вы вернете String, ни больше, ни меньше , String как есть, это простая переменная стека, которая будет просто скопирована туда, где она должна быть.

Вы правы относительно необходимости распределенных данных.

Это деталь реализации. Чтобы понять, где происходит распределение, мы должны посмотреть, что на самом деле является String.

В зависимости от того, как вы на это смотрите, может быть неудивительно, что оно выделяется внутри, и по этой конкретной причине c, Vec используется, поскольку он абстрагирует распределение необработанных данных.

Это буквальное определение String:

pub struct String {
    vec: Vec<u8>,
}

Когда вы создаете новый String, как вы можно видеть, что Box.

Vec не создано, а Vec отвечает за распределение и освобождение данных.

String, с другой стороны, отвечает за абстрагирование необработанных данных в то, что мы понимаем под типичной строкой.

4 голосов
/ 09 февраля 2020

String управляет собственным буфером символов. Это больше похоже на C ++ std::string, чем char*. И вы определенно можете возвращать локальные переменные, которые копируются или перемещаются в зависимости от ситуации, почему вы не смогли бы это сделать?

2 голосов
/ 09 февраля 2020

Возвращаемые значения обычно передаются вызывающей стороне через регистр или два. На x86-64 (который имеет 64-разрядные регистры) используется rax, и специально для System V AMD64 ABI , rdx может дополнять rax для возврата значения до 128 бит (16 байтов).

Однако String больше этого: на x86-64 это занимает 24 байта. Если тип возвращаемого значения функции слишком велик для прохождения через регистры, функция получит дополнительный параметр, который будет содержать адрес, по которому следует хранить возвращаемое значение. Часто этот указатель ссылается на локальную переменную в кадре стека вызывающей стороны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...