C++ move семантика, как реализовать?

115
22 июня 2021, 04:40

Прошу помочь разобраться с реализацией move семантики на моём примере

Имею простой класс своей строки

class DynamicString
{
public:
    char* CharArray;
    int Length;
    DynamicString(char* charArray, int length);
    ~DynamicString();
    DynamicString(const DynamicString &dsObject);
    DynamicString&operator= (const DynamicString &dsObject);
}

Пробую реализовать операторы копирования и присваивания пока без Move семантики

DynamicString::~DynamicString()
{
    delete[] CharArray;
    CharArray = nullptr;
}
DynamicString::DynamicString(const DynamicString & dsObject)
{
    Length = dsObject.Length;
    CharArray = new char[Length];
    for (int i = 0; i < Length; i++)
        CharArray[i] = dsObject.CharArray[i];
}
DynamicString & DynamicString::operator=(const DynamicString & dsObject)
{
    if (Length == dsObject.Length)
        for (int i = 0; i < Length; i++)
            CharArray[i] = dsObject.CharArray[i];
    else
    {
        delete[] CharArray;
        Length = dsObject.Length;
        CharArray = new char[Length];
        for (int i = 0; i < Length; i++)
            CharArray[i] = dsObject.CharArray[i];
    }
    return *this;
}

Читая различные ресурсы, как я понял, необходимо переставить ссылку массива с одного на другой. Что-то вроде CharArray = dsObject.CharArray; внутри копирования и присваивания, однако возникает вопрос, в этом случае, если один из объектов будет удален, разве не будет удалено содержимое второго объекта? И вопрос по памяти, разве не будет в этом случае утечки памяти, если теряется ссылка на изначальный объект?

Answer 1

При перемещении вы не просто переносите

Length = dsObject.Length;
CharArray = dsObject.CharArray;

но и переводите исходный объект в некоторое состояние типа нулевого - скажем,

dsObject.Length = 0;
dsObject.CharArray = nullptr;

(точнее, в такое состояние, которое спокойно будет принято деструктором и не приведет ни к каким проблемам типа повторного освобождения памяти). Работать с объектом после его перемещения в общем случае нельзя.

Answer 2

Ну здесь вам надо начать не с move семантики а с оператора=

DynamicString & DynamicString::operator=(const DynamicString & dsObject) {
  if (this == &bsObject) // так как если объект присваивается сам себе то мы просто возвращаем указатель this 
      return *this;
  else {
      delete[] CharArray;
      Length = dsObject.Length;
      CharArray = new char[Length];
      for (int i = 0; i < Length; i++)
          CharArray[i] = dsObject.CharArray[i];
      return *this;
  }
READ ALSO
Мне необходимо обнулить (либо поставить единичку) на одну из ножек микроконтроллера

Мне необходимо обнулить (либо поставить единичку) на одну из ножек микроконтроллера

Цель задания: Управлять лампочкой путем (замкнута/разомкнута) контакта преемника, который управляется микроконтроллеромЗадачей зажжением...

75
Как проверить логин и пароль пользователя в linux?

Как проверить логин и пароль пользователя в linux?

Пользователь вводит логин и пароль в консоль программы, есть ли возможность проверить из верность используя с++ linux api или bash?

86
Невалидный итератор после поиска

Невалидный итератор после поиска

Мне нужен класс в котором одно из полей(контейнер) будет подгружаться по мере необходимостиНапример когда происходит вызов begin() данные подгрузятся

99