Верно ли это понимание: если объект хранит в себе все, то копирование и перемещение — это на самом деле одно и то же?

Примеры «объектов, которые хранят в себе все или нет» в 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 на самом деле является мелкой копией. Если объект хранит в себе все, то глубокая и поверхностная копии — это одно и то же.

Ни один из приведенных вами примеров не является объектом. Кроме того, задавая вопрос, связанный с кодом, самый первый тег, который вам следует использовать, должен относиться к языку, который вы используете. Помещать это в тело сообщения бесполезно. Люди следят за тегами.

Ken White 25.08.2024 05:56

Это похоже на сценарий, основанный на прецедентах, поэтому на самом деле это зависит от того, какую проблему вы пытаетесь решить.

Some programmer dude 25.08.2024 06:00

И обратите внимание, что ExampleHasHeap2 даже невозможно скопировать. А из-за оптимизации коротких строк (SSO) ExampleHasHeap1 может вообще не использовать кучу.

Some programmer dude 25.08.2024 06:00

Также обратите внимание, что std::move на самом деле ничего не перемещает. По сути, это удобный актерский состав. Это слово скорее неправильное употребление.

user12002570 25.08.2024 06:08

Кроме того, using ExampleNoHeap2 = struct{...}; по большей части является необычным способом написания struct ExampleNoHeap2{...};.

user12002570 25.08.2024 06:13

Копирование и перемещение относятся к соответствующим конструкторам (операторам присваивания), это не обязательно связано с тем, как распределяются объекты.

Gene 25.08.2024 06:15
struct S { S(int v) : v(v) {} int v; S(S const &) = default; S(S&& o) : v(o.v) { o.v = 0; } } копирование отличается от перемещения, но не использует кучу.
Raymond Chen 25.08.2024 06:19

Вам требуется, чтобы в примере кода было объявлено 4 переменных, чтобы «они были объектами»? Пожалуйста, это не имеет смысла.

Erciyuanshagou 25.08.2024 06:21

Что такое отсутствие распределения кучи? Считается ли struct File { int fd = open("path", O_CREAT); ~File() { close(fd); } File(File&& other) : fd(0) { std::swap(fd, other.fd); } }; таковым?

3CxEZiVlQ 25.08.2024 06:24

Если вы собираетесь сравнивать несколько языков, я не уверен, что существует универсальное значение для «перемещения» объектов. В C++ этот термин имеет довольно специфическое значение, которое по сути представляет собой не что иное, как специальные правила разрешения перегрузки для определенных типов выражений. Он не имеет никакого значения в объектной модели и вообще не связан с длительностью хранения или распределением памяти.

user17732522 25.08.2024 06:25

@3CxEZiVlQ Это считается «выделением кучи». Потому что не все данные хранятся в структуре ifself.

Erciyuanshagou 25.08.2024 06:27

И «копирование», и «перемещение» означают разные вещи в C++ и Rust. Я предлагаю вам сосредоточиться на одном за раз.

kmdreko 25.08.2024 06:33

Похоже, вы предполагаете, что, поскольку код на разных языках выглядит одинаково, внутри языков делаются схожие вещи. Это неправда.

Pepijn Kramer 25.08.2024 06:42

@PepijnKramer Так что же они делают? Почему они не похожи? Можете ли вы немного уточнить свое утверждение?

Erciyuanshagou 25.08.2024 07:01

Например, в C# есть ссылочная семантика, а памятью управляет сборщик мусора. C++ позволяет вам явно использовать стек или динамически выделяемую память, а время жизни в основном определяется областями действия. Копирование и перемещение в C++ — это не одно и то же. Когда вы перемещаетесь, вы также передаете «право собственности», копирование на самом деле означает... создание копии (в памяти). Справочник Область C++ и C++ RAII

Pepijn Kramer 25.08.2024 09:34

В вашем вопросе много неточных моментов: во-первых, вы упоминаете «копировать» и «перемещать», как если бы эти термины имели абсолютное значение, но обычно жаргон каждого языка программирования переопределяет их в соответствии со своей моделью памяти (или не делает этого). не используйте их, когда они неактуальны). Более того, свойство объекта «хранить все в себе» само по себе немного нечетко определено. Это частично совпадает с понятием Copyдоступного типа в Rust, но опять же, это имеет смысл только в контексте Rust. Я не думаю, что это имеет смысл в C++.

jthulhu 25.08.2024 10:48

Кроме того, я не уверен, что вы подразумеваете под «языками распределения памяти на основе стека и кучи». Стек и куча — это абстракция, предоставляемая вашей операционной системой и (в некоторой степени) аппаратным обеспечением вашего компьютера. Следовательно, за исключением того, что вы представляете себе очень нишевый язык программирования, который работает только в нишевой операционной системе на нишевом оборудовании, на котором нет понятия кучи и стека, не существует языка программирования распределения памяти без стека и кучи.

jthulhu 25.08.2024 10:50
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
17
135
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Действительно, если объект хранит все свои данные внутри себя, не обращаясь к внешним данным, дублирование и перемещение объекта по существу даст тот же результат. Это происходит потому, что обе операции дублируют всю информацию, содержащуюся в объекте. В предоставленном вами коде C++ копирование и перемещение EverythingInMyself приведет к тому же результату, поскольку все данные хранятся внутри самого объекта.

По крайней мере, в C++ это обычно справедливо для классов без ошибок проектирования. Но поскольку в конструкторах/назначениях копирования/перемещения может быть произвольный код, это не может быть справедливо для произвольных классов.

Единственное исключение, о котором я могу подумать (где это не так и не является ошибкой проектирования), — это сброс перемещенных элементов к некоторым значениям по умолчанию.

Другие вопросы по теме