【发布时间】:2021-07-07 17:38:06
【问题描述】:
我有一个自定义类型的 Tree 的 std::vector,并且我有一个循环将所有 Tree 推回向量。问题是:我需要推回 temporary Tree 对象,但同时,我必须避免它们被释放(我想将 rvalue 引用构造函数 添加到 Tree 类可以解决问题,但它没有)。
树类:
class Tree
{
public:
Tree();
Tree(Coords, Pixel, 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.log->texture, tree.log->height)),
crown(new Crown(tree.crown->coords, tree.crown->texture, 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)));
}
}
}
【问题讨论】:
-
如果你构造它们,你需要解构它们,即使移动了......
-
真正的问题是什么?你的班级关注rule of 3/5/0吗?
-
如果您可以包含
Trees类的代码,则响应可能会更好。在现代 C++ 中,您通常可以通过不定义构造函数或赋值运算符来获得最佳结果。你也可以放置而不是推到向量上。 -
@DarkoNaito_09 -- 如果确定一个对象是可复制的,那么复制的含义必须具有逻辑意义。例如,C++ 中的流类是不可复制的。制作文件流的副本意味着什么?正在写入或读取两个文件?这就是为什么流是不可复制的,因为它没有意义。但是,流类是可移动的,也许你应该放弃复制并让类只是可移动的。
-
另外,请注意,复制是 编译器 可以做的事情,而您实际上不需要做任何明确的事情。因此,现在您将在整个程序运行过程中获得副本,并且您几乎无法控制它。这就是为什么复制必须简单、高效且没有(可见)副作用的原因。
标签: c++ constructor initialization rvalue-reference temporary-objects