我应该调用void构造函数来重置移动语义中的对象吗?

问题描述 投票:-1回答:1

据我所知,void构造函数的目的是将所有元素从选择状态重置到正确的新生状态。

所以。

  • 我应该在移动语义中调用void构造函数来重置对象吗?
  • 我应该像这样写reset()和invoke()吗?
  • void构造函数应该做什么?
  • 我的字符串实现是否足够好?
#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;
};
c++ constructor move-semantics
1个回答
2
投票

我在这里只想解决关于move语义的问题,因为你应该一次只问一个问题。

移动构造函数一般可以让对象处于任何它想要的状态,只要你把后置条件记录下来,让类的用户知道会发生什么。

例如,在C++标准库中的许多类都声明一个move-from对象处于一个 未详,但有效 状态。 这意味着你不能对对象的状态做任何假设,但你可以做到 问事 或者你可以手动将其重置为清除状态。("正确 "的说法是,你只能调用对象的没有前提条件的方法)。

我相信之所以选择这条路线,是因为实现移动语义的最有效方法是简单地交换目标对象和源对象的值。 通常这是很好的,因为在很多情况下,源对象要么会被立即销毁,要么会被手动清除。

你通常的做法是。

  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. 在移动构建时,先构建默认状态,然后交换。

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

这种模式有多个优点 最大的优点是,它的 真的 难于上青天 swap() 方法正确工作。另一个优点是,它迫使你支持交换,这在很多不同的场景下,它本身就很有用。


0
投票

在C++中,一个destructor就像它的名字一样,摧毁了你的对象,这意味着在调用它之后,你的对象的底层内存已经被释放了,这也意味着你不能再访问它,因为它在你的应用程序中不存在。这也意味着你不能再访问它,因为它不在你的应用程序中。

如果你想重置一个对象,你可以直接调用你的 reset 函数,它将按照你想要的方式清除数据。如果你想要一个干净的对象副本,你可以使用移动赋值操作符,然后调用 reset 复制的对象上。

请注意,在复制对象上设置 cstrnullptr 并不能释放内存。以下是你应该做的。

~STR_imp() { delete cstr; }

STR_imp& reset()
{
  delete cstr;
  cstr = nullptr;
  return *this;
}
© www.soinside.com 2019 - 2024. All rights reserved.