я должен вызвать конструктор void для сброса объекта в ходу semanti c? - PullRequest
0 голосов
/ 22 апреля 2020

Как я знаю,
цель конструктора void - сбросить все элементы из состояния choas в надлежащее состояние новорожденного.
и этот статус мне вполне подходит для того, чтобы сделать это после кражи данных из rvalue referance.
но кажется, что это инвиль для прямого вызова конструктора void, и размещение-новый не работает для этого.

, поэтому

  • если я вызову void конструктор для сброса объекта в движении semanti c?
  • я должен написать reset () и invoke () как этот?
  • что должен делать конструктор void?
  • is моя строка достаточно хороша?
#include <cstring>


class STR_imp
{
    char* cstr;

    static size_t getSize(const char* incstr)
    {
        return std::strlen(incstr)+1;
    };
    STR_imp& fillBy(const char* incstr)
    {
        for(int i=0,size=getSize(incstr);i<size;i++)
            this->cstr[i]=incstr[i];
        return *this;
    };
    STR_imp& reset()
    {
        this->cstr=nullptr;
        return *this;
    };
    STR_imp& invoke()
    {
        if(this->cstr!=nullptr)
            delete[] this->cstr;
        return *this;
    };

    public:
        STR_imp():cstr(nullptr)
        {};
        ~STR_imp()
        {this->invoke().reset();};

        STR_imp(const char* const& incstr);//splited for reading
        STR_imp(char*&& incstr):cstr(incstr)
        {
            incstr=nullptr;
        };
        STR_imp(const STR_imp& instr);//splited for reading
        STR_imp(STR_imp&& instr):cstr(instr.cstr)
        {
            instr.reset();
        };
        STR_imp& operator= (const char* const& incstr);//splited for reading
        STR_imp& operator= (char*&& incstr)
        {
            this->invoke();
            this->cstr=incstr;
            incstr=nullptr;
            return *this;
        };
        STR_imp& operator= (const STR_imp& instr);//splited for reading
        STR_imp& operator= (STR_imp&& instr)
        {
            this->invoke();
            this->cstr=instr.cstr;
            instr.reset();
            return *this;
        };
        char* operator() ()
        {
            return this->cstr;
        };
};
STR_imp::STR_imp(const char* const& incstr):cstr(new char[getSize(incstr)])
{
    this->fillBy(incstr);
};
STR_imp::STR_imp(const STR_imp& instr):cstr(new char[getSize(instr.cstr)])
{
    this->fillBy(instr.cstr);
};
STR_imp& STR_imp::operator= (const char* const& incstr)
{
    this->invoke();
    this->cstr=new char[getSize(incstr)];
    this->fillBy(incstr);
    return *this;
};
STR_imp& STR_imp::operator= (const STR_imp& instr)
{
    this->invoke();
    this->cstr=new char[getSize(instr.cstr)];
    this->fillBy(instr.cstr);
    return *this;
};

Ответы [ 2 ]

2 голосов
/ 22 апреля 2020

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

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

Я считаю, что этот маршрут был выбран, потому что наиболее эффективный способ реализации семантики перемещения - просто поменяться местами. значения целевых и исходных объектов. Обычно это хорошо, потому что во многих сценариях ios исходный объект либо будет уничтожен сразу, либо очищен вручную.

Обычно вы можете сделать это так:

  1. Реализуйте действительный метод swap():

    void STR_imp::swap(STR_imp & other) {
      std::swap(cstr, other.cstr);
    }
    
  2. При назначении перемещения просто поменяйте местами:

    STR_imp& STR_imp::operator=(STR_imp&& instr) {
      swap(instr);
      return *this;
    }
    
  3. В конструкции move создайте состояние по умолчанию и затем поменяйте местами:

    STR_imp::STR_imp(STR_imp&& instr) : STR_imp{} {
      swap(instr);
    }
    

Этот шаблон имеет несколько преимуществ. Самое большое преимущество в том, что действительно трудно ошибиться, если ваш метод swap() работает правильно. Другое преимущество заключается в том, что он заставляет вас поддерживать обмен, который полезен сам по себе во многих различных сценариях ios.

0 голосов
/ 22 апреля 2020

Деструктор в C ++ уничтожает ваш объект в соответствии с его именем, что означает, что после вызова его основная память вашего объекта была освобождена. Это также означает, что вы больше не можете получить к нему доступ, поскольку он отсутствует в вашем приложении.

Если вы хотите сбросить объект, вы можете просто вызвать функцию reset, которая очистит данные так, как вы хотите , Если вам нужна чистая копия вашего объекта, вы можете использовать оператор присваивания перемещения и затем вызвать reset для скопированного объекта.

Обратите внимание, что установка cstr в nullptr не освобождает память , Вот что вы должны сделать вместо этого:

~STR_imp() { delete cstr; }

STR_imp& reset()
{
  delete cstr;
  cstr = nullptr;
  return *this;
}
...