Изменяет ли конструктор перемещения память, на которую указывает «это»?

У меня есть некоторые недоразумения по поводу конструктора перемещения С++. Если компилятор неявно синтезирует конструктор перемещения, что будет делать этот конструктор перемещения? Будет ли просто "this" указывать на объект, который используется для инициализации? есть пример:

struct Foo {
    int i;
    int *ptr;
};

Foo x;
Foo y(std::move(x));

будет ли неявно синтезированный конструктор перемещения просто заставлять this в y указывать на память, в которой находится x? Если да, то как обеспечить, чтобы x можно было разрушить после перемещения (если x уничтожается, будут ли члены в y действительными)? если нет, то как работает конструктор перемещения y?

1. Нет, и 2. как работают операторы перемещения (по сравнению с тем, как работают копировщики), подробно рассматривается во множестве вопросов на этом сайте. этот например. И особенно этот.

WhozCraig 10.04.2022 10:28
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
1
1
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

will the implicitly synthesized move constructor just make this in y point to the memory that x is in?

синтезатор движения будет членское перемещение членами данных своих аргументов (x здесь) для создаваемого объекта (y здесь).

Также обратите внимание, что для встроенных типов, таких как int, перемещение аналогично копированию.


how to ensure that x is destructible after the move

Поскольку перемещение — это то же самое, что и копирование для встроенных типов, x и y не зависят друг от друга. Поэтому, когда x будет уничтожен, y не пострадает.


will the synthesized move constructor set the ptr of x to nullptr?

Нет, движок синтеза не сделает этого за вас. Он просто будет перемещать элементы данных по элементам. Для встроенных типов это означает то же самое, что и копирование.


if it does not do this, then the ptr of x will still point to the memory to which the ptr of y points, then you cannot safely destroy x.

В этом случае вам нужно будет написать определяемый пользователем движущийся элемент, который явно устанавливает ptr из x в nullptr, чтобы при уничтожении x не затрагивалось y.

как конструктор перемещения перемещает элементы типа int или string? Будет ли он просто копировать значения этих членов в инициализированный объект класса?

kaiyu wei 10.04.2022 10:39

И установит ли синтезированный конструктор перемещения ptr из x значение nullptr? если он этого не сделает, то ptr из x все равно будет указывать на память, на которую указывает ptr из y, тогда вы не сможете безопасно уничтожить x.

kaiyu wei 10.04.2022 10:47

@kaiyuwei Для встроенных типов, таких как int, move это то же самое, что копирование. Больше можно найти здесь: Имеют ли встроенные типы семантику перемещения?. То есть для встроенных типов move является копией.

Anoop Rana 10.04.2022 10:57

@kaiyuwei Нет, синтезатор движения не установит ptr из x на nullptr. Он просто перемещает элементы данных из x в y, не делая ничего другого. Также обратите внимание, что для элементов данных встроенного типа, таких как int, перемещение аналогично копированию. Итак, x и y не зависят друг от друга. Если оба указателя x и y указывают на одну и ту же память, вам нужно будет написать собственный конструктор перемещения, который установит x в nullptr. Синтезированный ctor не сделает этого за вас.

Anoop Rana 10.04.2022 11:08

@kaiyuwei Вам придется написать определяемый пользователем механизм перемещения, который явно устанавливает ptr из x на nullptr, чтобы при уничтожении xy не затрагивалось.

Anoop Rana 10.04.2022 11:15

will the implicitly synthesized move constructor just make this in y point to the memory that x is in?

Как заметил Anoop, он будет вызывать конструктор перемещения для каждого члена источника, который нужно переместить (x), на элементы назначения (y или this, если вы представляете себя «внутри» этого синтезированного конструктора перемещения).

Итак, в вашем примере:

  • intx.i будет перемещен на y.i (this->i)
  • int*x.ptr будет перемещен на y.ptr (this->ptr).

Обратите внимание, что эти конкретные перемещения будут выполняться путем копирования.

how to ensure that x is destructible after the move (if x is destroyed, will members in y be valid)?

Это всегда разрушаемо. Что касается того, является ли он «действительным», это зависит от того. Конструкция перемещения по умолчанию фактически была копией. Теперь два объекта указывают на то, на что указывает x.ptr. Если этот int был ресурсом, «принадлежавшим» x (возможно, ресурс был строкой целых чисел в конце 0 в куче), то вы только что «поделились» этим ресурсом.

Если вы не хотите «делиться» им, вы могли бы явно написать конструктор перемещения для Foo, который сбрасывает указатель «перемещенного из» объекта или каким-то образом помечает его как недействительный.

struct Foo {
  ...
  Foo(Foo&& other) {
    this->i = other.i;
    this->ptr = other.ptr;
    other.ptr = nullptr;
  }
}

В общем, лучше вообще не полагаться на "перемещенные" объекты, т.е. позаботиться о том, чтобы они были уничтожены как можно скорее.

Спасибо, Жоао, поскольку x.ptr и y.ptr указывают на один и тот же объект, как вы можете говорить, что x разрушаем? поскольку, если вы уничтожите x, то объект, на который указывает y.ptr, также будет уничтожен, что сделает ```y.ptr''' недействительным.

kaiyu wei 10.04.2022 11:12

Правильно, но в примере, который вы впервые опубликовали, такого деструктора члена ptr не было! Таким образом, то, на что указывает ptr, будет уничтожено нет. Если есть мы такой деструктор, то этот деструктор, вероятно, должен проверять, является ли ptrnullptr, а не уничтожать его. И это хорошая причина определить конструктор перемещения, как я предложил.

Joao Tavora 10.04.2022 11:28

Теперь мне достаточно ясно. Большое спасибо!

kaiyu wei 10.04.2022 11:43

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