对象如何将自己添加到对象类中的向量中?

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&lt;Particle&gt; 正在存储粒子 按值,因此它不能将“自身”添加到该向量中,它可以添加 副本,但这可能是不是你想要的。

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_backmake_unique 解决方案。 我会建议“根本不要在构造函数中这样做”的解决方案。 @user253751 我的意思是particles.emplace_back(position);particles.push_back(std::make_unique&lt;Particle&gt;(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;
;

这样做的乐趣在于,您现在可以创建一个不会被强制撞到向量中的粒子(这可能对测试/序列化/其他用途很有用);但是你已经做到了,如果你去你的粒子组;您不必担心粒子是如何存储的。 (例如,当您意识到由于随机删除而实际上想要一个列表时;您不想重新编写所有内容!)

【讨论】:

以上是关于对象如何将自己添加到对象类中的向量中?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中向向量中添加新对象

如何将对象存储在向量中的对象中? (C++)

如何将对象添加到另一个类中的 vector<object> ?

将派生类中的对象插入到所述对象的另一个实例中(使用 vector.insert 函数)C++

c++ 类中的意外输出并将对象复制到另一个对象

我自己的堆栈类中的 C++ 奇怪行为