简体   繁体   English

在C ++中创建对象时,如何将对象指针推向矢量?

[英]How to push object pointer to vector when object is created in C++?

I am trying to add my object pointer into vector same time object is created. 我试图在创建对象的同时将对象指针添加到向量中。 Currently I have done it in object's constructor but now I have heard that this is a wrong way because object isn't completely created on that point. 目前,我已经在对象的构造函数中完成了此操作,但是现在我听说这是一种错误的方法,因为此时尚未完全创建对象。

MyObject class constructor: MyObject类的构造函数:

// MyObject constructor
MyObject::MyObject() {
    // add object to vector of all objects
    MyObjectManager::Instance()->objects.push_back(this);
}

MyObject is just a base class for objects. MyObject只是对象的基类。 I have also MyRectangle class that is inherited from MyObject so when I create new MyRectangle then MyObject constructor is called and my newly created object is pushed into MyObjectManager's vector. 我还有从MyObject继承的MyRectangle类,因此当我创建新的MyRectangle时,将调用MyObject构造函数,并将新创建的对象推入MyObjectManager的向量中。

MyObjectManager is a singleton class that keeps list of all objects and calls their virtual Draw function very frequently. MyObjectManager是一个单例类,可保留所有对象的列表并非常频繁地调用其虚拟Draw函数。 Is that the problem? 那是问题吗? MyObjectManager might call object's Draw function before object is completely created? MyObjectManager可能在对象完全创建之前调用对象的Draw函数吗?

I could make separate method for adding object to vector. 我可以制作将对象添加到向量的单独方法。 Something like this: 像这样:

MyObject::Create() {
    // add object to vector of all objects
    MyObjectManager::Instance()->objects.push_back(this);
}

But then I have to use it like this: 但是然后我必须像这样使用它:

MyRectangle *rect = new MyRectangle(0.5, 0.5, 0.1, 0.1);
rect->Create();

I just want to be able to instantiate new object simply by constructor like this: 我只希望能够简单地通过构造函数实例化新对象,如下所示:

MyRectangle *rect = new MyRectangle(0.5, 0.5, 0.1, 0.1);

You can do that in your constructor, isn't it? 您可以在构造函数中做到这一点,不是吗?

MyRectangle::MyRectangle(const float& a, const float& b, const float& c, const float& d) {
  this->Create();
}

If you have special MyObjectManager class, you can use it also as a factory for objects. 如果您有特殊的MyObjectManager类,则也可以将其用作对象的工厂。 To illustarate it consider code: 为了说明它,请考虑以下代码:

struct MyObjectManager {

    template <typename T, typename... Args>
    T * createObject(Args... args) {
        T *ret = new T(args...);
        m_objects.push_back(ret);
        return ret;
    }

    std::vector<MyObjects *> m_objects;
};

Object creation: 对象创建:

MyRectangle *rect = MyObjectManager::Instance()->createObject<MyRectangle>(1.0, 2.0, 3.0, 4.0);

Maybe you could consider using a factory pattern: 也许您可以考虑使用工厂模式:

MyRectangle * factoryMyRectangle(float x, float y, float w, float h)
{
    MyRectangle *rect = new MyRectangle(x,y,w,h);
    rect->Create();
    return rect;
}

that you can call: 您可以致电:

MyRectangle *rect = factoryMyRectangle(0.5, 0.5, 0.1, 0.1);

A lot depends on context. 在很大程度上取决于上下文。 If the push_back is the last instruction in the constructor, and there are no derived classes, there should be no problem. 如果push_back是构造函数中的最后一条指令,并且没有派生类,则应该没有问题。 Similarly, if you are in a single threaded environment (and since you don't do any locking, you must be), and the derived classes don't do anything through the pointer in the vector, there is no problem. 同样,如果您处于单线程环境中(并且由于您没有做任何锁定,那么必须这样做),并且派生类对向量中的指针没有任何作用,那么就没有问题。 You're allowed to have pointers to not yet fully-constructed objects, as long as you don't try to use the actual object they point to. 只要您不尝试使用它们指向的实际对象,就可以使用它们指向尚未完全构造的对象的指针。

The one case where this could be a problem is if you do it in a base class constructor in a multithreaded environment. 这可能是一个问题的情况是,如果您在多线程环境中的基类构造函数中执行此操作。 If you push the pointer to the not yes fully constructed object, and then another thread takes over, looks up the object in the vector, and tries to use it, you are in trouble. 如果将指针推到不是完全构建的对象上,然后另一个线程接管,在向量中查找该对象,然后尝试使用它,则会遇到麻烦。 There are various techniques to handle this: the most common is probably to use a factory function to construct all objects, and have the factory function do the push_back , after the constructor has finished. 有多种技术可以解决此问题:最常见的方法可能是使用工厂函数构造所有对象,并在构造函数完成后让工厂函数执行push_back So you would never call new MyRectangle(...) outside of the factory function. 因此,您永远不会在工厂函数之外调用new MyRectangle(...) (Typically, the factory function will be a static member, and the constructor will be private, so you can guarantee this.) (通常,factory函数将是一个静态成员,而构造函数将是私有的,因此可以保证这一点。)

Note that if you do use the factory function, you'll probaby want to keep the results of new in a smart pointer until the push_back has finished: 请注意,如果你使用的工厂函数,你会probaby要保持成果new的智能指针,直到push_back完成:

std::unique_ptr<MyRectangle> tmp( new MyRectangle(...) );
MyObjectManager::Instance()->objects.push_back( tmp.get() );
tmp.reset()

If you can guarantee there will be no access but mere storage to the object before it is fully constructed, there shouldn't be a problem with using the this pointer like you did. 如果可以保证在完全构造对象之前没有访问权限,而只能存储对象,那么使用this指针应该不会有问题。 The guarantee is broken if there is another thread handling draw updates which, for instance, polls all objects in the manager class and calls their draw function regularly. 如果还有另一个线程处理绘图更新​​,则该保证将被破坏,例如,该更新轮询管理器类中的所有对象并定期调用其draw函数。

Look at this question and this one for more information. 看看这个问题, 一个以获取更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM