对象如何将自己添加到对象类中的向量中?
Posted
技术标签:
【中文标题】对象如何将自己添加到对象类中的向量中?【英文标题】:How would a object add itself to a vector inside the object's class? 【发布时间】:2019-12-18 13:55:53 【问题描述】:我对课程很陌生。
粒子如何将自己添加到类中的 std::vector 中?
我的代码:
std::vector<Particle> particles;
class Particle
public:
Particle(sf::Vector2f position)
particles.push_back(/*add this Particle into vector particles*/);
;
【问题讨论】:
如果你不想存储这个对象的副本,而是对象本身在vector中,这是不可能的。对于副本使用particles.push_back(*this);
@eerorika 实际上可以,只是在类型完成之前不能使用它,它在构造函数中:timsong-cpp.github.io/cppwp/vector#overview-4
@NathanOliver-ReinstateMonica 够公平的。但是您仍然无法在声明 Particle
之前定义变量。
@eerorika 是的,至少需要声明。
【参考方案1】:
std::vector<Particle>
正在存储粒子 按值,因此它不能将“自身”添加到该向量中,它可以添加 副本,但这可能是不是你想要的。
emplace_back
可用于将粒子构造到向量本身:
particles.emplace_back(position); // Will call Particle(position)
如果您确实想要一份副本,只需遵循 this
指针,但这可能会造成混淆。不要在复制/移动构造函数或复制/移动赋值运算符中执行此操作,因为它们可以在插入/删除/等过程中由向量本身调用。
Particle(sf::Vector2f position)
particles.push_back(*this);
否则,您可以将指针存储在向量中。这带来了额外的问题,例如谁负责释放它们,并且对于诸如粒子系统之类的东西可能会对性能产生重大影响。
std::vector<Particle*> particles;
class Particle
public:
Particle(sf::Vector2f position)
particles.push_back(this); // Dangerous
// If an exception happens after push_back this object will be destroyed,
// but particles will still contain that now invalid pointer.
;
...
auto particle = new Particle(position); // Who deletes this?
如果粒子负责删除,您可以使用std::unique_ptr
,但在构造函数中这样做可能不安全。
std::vector<std::unique_ptr<Particle>> particles;
class Particle
public:
Particle(sf::Vector2f position)
particles.push_back(std::unique_ptr<Particle>(this)); // Dangerous
// If an exception happens in push_back or after this in the constructor
// the exception will cause this Particle to be destroyed, but this unique_ptr
// will be left with an invalid pointer, and try and delete it as well.
;
...
new Particle(position);
最好在外面做,在其他功能中。
std::vector<std::unique_ptr<Particle>> particles;
class Particle
public:
Particle(sf::Vector2f position)
;
...
particles.push_back(std::make_unique<Particle>(position));
【讨论】:
请注意,如果您曾经堆栈分配Particle
对象,这将崩溃并烧毁。
@Botje 有很多其他方法可以使堆栈对象或 C++ 中的任何对象出错。我绝对建议emplace_back
或make_unique
解决方案。
我会建议“根本不要在构造函数中这样做”的解决方案。
@user253751 我的意思是particles.emplace_back(position);
或particles.push_back(std::make_unique<Particle>(position));
。也许会看到让它更清晰。【参考方案2】:
如果您只需要将粒子的副本推送到向量,那么您可以取消引用 this
指针并将其推送到向量中,如下所示:
particles.push_back(*this)
虽然这会创建一个副本,但它并不引用调用它的原始对象,而是一个全新的对象。如果要将原始粒子推送到向量,则需要将向量存储为Particle*
。然后,您可以像这样将当前粒子推送到向量:
std::vector<Particle*> particles;
class Particle
public:
Particle(/* Your constructor args */)
particles.push_back(this)
【讨论】:
请注意,如果您曾经堆栈分配Particle
对象,这将崩溃和烧毁。
崩溃和壮观...这非常吸引人,应该尽可能在任何地方使用:P【参考方案3】:
我建议你放弃迄今为止的所有答案;并创建一个新的包装类;因为我认为从根本上说你的设计很弱。
class Particle ;
struct ParticleGroup
Particle& createParticle()
particles.push_back(Particle());
return particles.back();
std::vector<Particle> particles;
;
这样做的乐趣在于,您现在可以创建一个不会被强制撞到向量中的粒子(这可能对测试/序列化/其他用途很有用);但是你已经做到了,如果你去你的粒子组;您不必担心粒子是如何存储的。 (例如,当您意识到由于随机删除而实际上想要一个列表时;您不想重新编写所有内容!)
【讨论】:
以上是关于对象如何将自己添加到对象类中的向量中?的主要内容,如果未能解决你的问题,请参考以下文章
如何将对象添加到另一个类中的 vector<object> ?