MrNexeon
@MrNexeon

Что происходит с переменной / указателем в памяти после его обнуления?

Добрый день, еще только изучаю c++, столкнулся с такой темой как "семантика переноса" и появился один вопрос.

Допустим у меня есть некий класс, который имеет указатель на динамический массив и переменную int size, которая хранит размер массива.
class SomeClass { 
int size; 
int *element; 
public: 
SomeClass(int i) { 
size = i; 
element = new int[size]; 
} 
SomeClass( SomeClass &&other ) { 
size = other.size; 
element = other.element; 
other.size = 0; 
other.element = nullptr; 
} 
};

int main() {
SomeClass a1(5);
SomeClass a2 = move(a1); //происходит вызов конструктора переноса
}


Когда я использую конструктор переноса, я тем самым переношу ресурсы одного объекта (старого, в данном коде это other) другому (новому), а конкретно копирую значение size, а так же добавляю новый указатель на область памяти массива старого объекта. При этом член-size и указатель на массив старого объекта обнуляю с помощью 0 и nullptr. Но теперь вопрос..

Что произойдет после данной вышеописанной операцией с членом size и указателем старого объекта (other)? Они останутся в памяти вместе с объектом? Или при нулевом значение они занимают незначительную область памяти?

p.s. надеюсь вопрос сформулировал правильно. пробовал читать различную документацию, но так и не нашел ответа на свой вопрос.
  • Вопрос задан
  • 518 просмотров
Решения вопроса 1
@MarkusD Куратор тега C++
все время мелю чепуху :)
Смотрю, на этот вопрос все еще нет ответов, поэтому добавлю немного отсебятины.

Что произойдет после данной вышеописанной операцией с членом size и указателем старого объекта (other)? Они останутся в памяти вместе с объектом? Или при нулевом значение они занимают незначительную область памяти?


Давай обратимся к C++ Core Guidelines за разъяснениями.
Советую, кстати, детально изучить от корки до корки.

https://github.com/isocpp/CppCoreGuidelines/blob/m...
В результате перемещения источник должен оставаться в состоянии, когда им можно дальше пользоваться.

Наш объект класса SomeClass может быть выделен как на стеке, так и в куче. Когда мы его перемещаем, мы перемещаем только внутренности объекта, а не сам объект. После перемещения объект все так же остается жить и должен иметь возможность правильно удалиться как со стека, так и из кучи. Ответственность за это полностью лежит на разработчике класса. Но удаляет объект не семантика перемещения и, тем более, не конструктор перемещения. функция std::move является всего лишь декоратором, который меняет тип объекта с lvalue на rvalue. Она не занимается удалением или очисткой объекта.

После перемещения объект можно дальше использовать. Если следовать гайдлайну, то после перемещения объект должен стать таким, как будто он был только что сконструирован стандартным конструктором. Объект можно снова заполнить и снова переместить. И так - сколько угодно раз.
А сам объект всегда занимает один и тот же объем памяти, определенный его классом.

Так же по теме:
https://github.com/isocpp/CppCoreGuidelines/blob/m...
https://github.com/isocpp/CppCoreGuidelines/blob/m...
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
petermzg
@petermzg
Самый лучший программист
Ты просто копируешь значение указателя.
other.element = nullptr;
Обнуляешь значение указателя и это никак не влияет на сами выделенные данные.
Ответ написан
slinkinone
@slinkinone
Агент "Везде успеть"
Обычно говорят конструктор копирования, но это так, к слову.
1. Ответ на ваш вопрос. Переменная size примет значение other.size, *element примет значение *other.element (как указатель). Причем после вызова конструктора объект other изменится, т.к. он передаётся по адресу.
2. Это неправильная реализация - вы же копируете. Объект other не должен изменяться. И для указателя a2 нужно копировать не значения указателя, а значения, которые хранятся по этому указателю. Иначе у вас получится так, что члены двух классов ссылаются на одну и туже область памяти и могут её менять. Т.е. если по указателю a1.element изменятся значения, то они изменятся и в a2. Нужно при копировании сначала освободить всю память *element, затем выделить заново под нужный размер, и уже потом скопировать значения в эту область.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы