微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C++ 使用复制构造函数避免临时对象销毁

如何解决C++ 使用复制构造函数避免临时对象销毁

我有一个 Treestd::vector一个自定义类型,并且我有一个循环将全部 Tree 推回向量。问题是:我需要推回 temporary Tree 对象,但同时,我必须避免它们被释放(我认为向 Tree添加一个 rvalue 引用构造函数 可以解决这个问题,但它没有)。

树类:

class Tree
{
    public:
        Tree();
        Tree(Coords,Pixel,uint8_t);
        Tree(const Tree&);
        Tree(const Tree&&);
        ~Tree();

        Tree& operator=(const Tree&);
        Tree& operator=(const Tree&&);

        void draw();
        void chop(uint8_t);

        Coords getCoords() const {return log->coords;}

        const Log& getLog() const
        { 
            return *log;
        }

        const Crown& getCrown() const
        {
            return *crown;
        }

    private:
        Log*     log;
        Crown* crown;
};

Tree::Tree():
    log(nullptr),crown(nullptr)
{

}

Tree::Tree(Coords c,Pixel wd,Pixel lvs,uint8_t h):
    log(new Log(c,wd,h)),crown(new Crown({c.x,static_cast<coordsCounter>(c.y + h)},lvs,getRandBetweenEqu(3,4)))
{
    draw();
}

Tree::Tree(const Tree& tree):
    log(new Log(tree.log->coords,tree.log->texture,tree.log->height)),crown(new Crown(tree.crown->coords,tree.crown->texture,tree.crown->width))
{
    draw();
}

Tree::Tree(const Tree&& tree):
    log(new Log(tree.log->coords,tree.crown->width))
{
    draw();
}

Tree& Tree::operator=(const Tree& tree)
{
    if(log != nullptr) delete log;
    if(crown != nullptr) delete crown;

    log   = new Log(*tree.log);
    crown = new Crown(*tree.crown);

    return *this;
}

Tree& Tree::operator=(const Tree&& tree)
{
    if(log != nullptr) delete log;
    if(crown != nullptr) delete crown;

    log   = new Log(*tree.log);
    crown = new Crown(*tree.crown);

    return *this;
}

void Tree::draw()
{
    log->draw();
    crown->draw();
}

Tree::~Tree()
{
    chop(0);
}

void Tree::chop(uint8_t h)
{
    if(crown != nullptr)
    {
        delete crown;
        crown = nullptr;
    }

    if(h == 0)
    {
        if(log != nullptr)
        {
            delete log;
            log = nullptr;
        }
    } else
    {
        if(h <= log->height)
        {
            log->chop(h);
        }
    }
}

推回树的函数

void growTrees(uint8_t m,uint8_t M)
{
    Coords treeCoords;

    for(coordsCounter i = 5; i < grid.getMaxXY().x - 4; i += getRandBetweenEqu(m,M))
    {
        if((treeCoords = getFirstBlock({i,static_cast<coordsCounter>(grid.getMaxXY().y - 1)},'s',grasstexture) + Coords{0,1}) != Coords{0,1})
        {
            trees.push_back(Tree(treeCoords,woodTexture,leavesTexture,getRandBetweenEqu(minTreeHeight,maxTreeHeight)));
        }
    }
}

解决方法

您的移动构造函数/赋值运算符实际上是在复制对象,它们应该采用非常量右值引用并将移动的对象设置为某个空值。

Tree::Tree(Tree&& tree):
    log(std::exchange(tree.log,nullptr)),crown(std::exchange(tree.crown,nullptr))
{
    draw();
}
Tree& Tree::operator=(Tree&& tree)
{
    std::swap(tree.log,log);
    std::swap(tree.crown,crown);
    return *this;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。