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;
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...