Примеры «объектов, которые хранят в себе все или нет» в C++:
using EverythingInMyself1 = int[64];
using EverythingInMyself2 = struct {
bool flag;
int head;
uint8_t data[100];
};
using SomeDataMayNotInMyself1 = std::string;
using SomeDataMayNotInMyself2 = struct {
bool flag;
std::unique_ptr<uint8_t[]> data;
};
Примеры «объектов, которые хранят в себе всё или нет» в Rust:
type EverythingInMyself1 = [i32; 64];
struct EverythingInMyself2 {
flag: bool,
head: i32,
data: [u8; 100]
}
type SomeDataMayNotInMyself1 = String;
struct SomeDataMayNotInMyself2 {
flag: bool,
data: Vec<u8>
}
Верно для всех языков распределения памяти на основе стека и кучи? Потому что ход AFAIK на самом деле является мелкой копией. Если объект хранит в себе все, то глубокая и поверхностная копии — это одно и то же.
Это похоже на сценарий, основанный на прецедентах, поэтому на самом деле это зависит от того, какую проблему вы пытаетесь решить.
И обратите внимание, что ExampleHasHeap2 даже невозможно скопировать. А из-за оптимизации коротких строк (SSO) ExampleHasHeap1 может вообще не использовать кучу.
Также обратите внимание, что std::move на самом деле ничего не перемещает. По сути, это удобный актерский состав. Это слово скорее неправильное употребление.
Кроме того, using ExampleNoHeap2 = struct{...}; по большей части является необычным способом написания struct ExampleNoHeap2{...};.
Копирование и перемещение относятся к соответствующим конструкторам (операторам присваивания), это не обязательно связано с тем, как распределяются объекты.
struct S { S(int v) : v(v) {} int v; S(S const &) = default; S(S&& o) : v(o.v) { o.v = 0; } } копирование отличается от перемещения, но не использует кучу.
Вам требуется, чтобы в примере кода было объявлено 4 переменных, чтобы «они были объектами»? Пожалуйста, это не имеет смысла.
Что такое отсутствие распределения кучи? Считается ли struct File { int fd = open("path", O_CREAT); ~File() { close(fd); } File(File&& other) : fd(0) { std::swap(fd, other.fd); } }; таковым?
Если вы собираетесь сравнивать несколько языков, я не уверен, что существует универсальное значение для «перемещения» объектов. В C++ этот термин имеет довольно специфическое значение, которое по сути представляет собой не что иное, как специальные правила разрешения перегрузки для определенных типов выражений. Он не имеет никакого значения в объектной модели и вообще не связан с длительностью хранения или распределением памяти.
@3CxEZiVlQ Это считается «выделением кучи». Потому что не все данные хранятся в структуре ifself.
И «копирование», и «перемещение» означают разные вещи в C++ и Rust. Я предлагаю вам сосредоточиться на одном за раз.
Похоже, вы предполагаете, что, поскольку код на разных языках выглядит одинаково, внутри языков делаются схожие вещи. Это неправда.
@PepijnKramer Так что же они делают? Почему они не похожи? Можете ли вы немного уточнить свое утверждение?
Например, в C# есть ссылочная семантика, а памятью управляет сборщик мусора. C++ позволяет вам явно использовать стек или динамически выделяемую память, а время жизни в основном определяется областями действия. Копирование и перемещение в C++ — это не одно и то же. Когда вы перемещаетесь, вы также передаете «право собственности», копирование на самом деле означает... создание копии (в памяти). Справочник Область C++ и C++ RAII
В вашем вопросе много неточных моментов: во-первых, вы упоминаете «копировать» и «перемещать», как если бы эти термины имели абсолютное значение, но обычно жаргон каждого языка программирования переопределяет их в соответствии со своей моделью памяти (или не делает этого). не используйте их, когда они неактуальны). Более того, свойство объекта «хранить все в себе» само по себе немного нечетко определено. Это частично совпадает с понятием Copyдоступного типа в Rust, но опять же, это имеет смысл только в контексте Rust. Я не думаю, что это имеет смысл в C++.
Кроме того, я не уверен, что вы подразумеваете под «языками распределения памяти на основе стека и кучи». Стек и куча — это абстракция, предоставляемая вашей операционной системой и (в некоторой степени) аппаратным обеспечением вашего компьютера. Следовательно, за исключением того, что вы представляете себе очень нишевый язык программирования, который работает только в нишевой операционной системе на нишевом оборудовании, на котором нет понятия кучи и стека, не существует языка программирования распределения памяти без стека и кучи.





Действительно, если объект хранит все свои данные внутри себя, не обращаясь к внешним данным, дублирование и перемещение объекта по существу даст тот же результат. Это происходит потому, что обе операции дублируют всю информацию, содержащуюся в объекте. В предоставленном вами коде C++ копирование и перемещение EverythingInMyself приведет к тому же результату, поскольку все данные хранятся внутри самого объекта.
По крайней мере, в C++ это обычно справедливо для классов без ошибок проектирования. Но поскольку в конструкторах/назначениях копирования/перемещения может быть произвольный код, это не может быть справедливо для произвольных классов.
Единственное исключение, о котором я могу подумать (где это не так и не является ошибкой проектирования), — это сброс перемещенных элементов к некоторым значениям по умолчанию.
Ни один из приведенных вами примеров не является объектом. Кроме того, задавая вопрос, связанный с кодом, самый первый тег, который вам следует использовать, должен относиться к языку, который вы используете. Помещать это в тело сообщения бесполезно. Люди следят за тегами.