开发者

Set pointer to null

开发者 https://www.devze.com 2023-03-20 22:20 出处:网络
I my c++ application I created some pointers to objects and added them to two vectors. Then I iterate through one vector till Ifound a object which satisfy a desired condition. If it satisfied I want

I my c++ application I created some pointers to objects and added them to two vectors. Then I iterate through one vector till I found a object which satisfy a desired condition. If it satisfied I want to NULL that pointer. The main thing is I want to make it to NULL at all places. The sample code is as below.

   #include <vector>

class Circle
{
public:
    Circle(int _iArea){iArea = _iArea;};
    ~Circle(){};
    void SetArea(int _iArea){ iArea = _iArea;};
    int GetArea(){return iArea;};

private:
    int iArea;
};

int _tm开发者_StackOverflow中文版ain(int argc, _TCHAR* argv[])
{
    Circle* pCircle1 = new Circle(10);
    Circle* pCircle2 = new Circle(20);
    Circle* pCircle3 = new Circle(30);
    Circle* pCircle4 = new Circle(40);


    std::vector<Circle*>vector_test1;
    vector_test1.push_back(pCircle1);
    vector_test1.push_back(pCircle2);
    vector_test1.push_back(pCircle3);
    vector_test1.push_back(pCircle4);

    std::vector<Circle*>vector_test2;
    vector_test2.push_back(pCircle1);
    vector_test2.push_back(pCircle2);
    vector_test2.push_back(pCircle3);
    vector_test2.push_back(pCircle4);

    std::vector<Circle*>::iterator itrVecTest1 = vector_test1.begin();
    std::vector<Circle*>::iterator itrVecTest1End = vector_test1.end();
    while(itrVecTest1 != itrVecTest1End)
    {
        int iType = (*itrVecTest1)->GetArea();
        if(iType ==10)
        {
            delete (*itrVecTest1);
            *itrVecTest1 = NULL;
        }
        ++itrVecTest1;
    }
    retrun 0;
}

Here pCircle1 satisfy the given condition and I want to delte it from all the places. Using this code I can make the pointer in the vector_test1 to null. But is there a way to make the set the same pointer in the vector_test2 at the same time without iterate through it?


Yes use Weak pointer.

int _tmain(int argc, _TCHAR* argv[])
{
    // If you don't have the latest version then
    // std::auto_ptr (Pointer should never be held in a RAW pointer,
    // always use some form of smart pointer (unless you don't own the pointer then RAW is fine).
    //
    std::unique_ptr<Circle> pCircle1 = new Circle(10);
    std::unique_ptr<Circle> pCircle2 = new Circle(20);
    std::unique_ptr<Circle> pCircle3 = new Circle(30);
    std::unique_ptr<Circle> pCircle4 = new Circle(40);


    // If you don't have the latest version then
    // boost::shared_ptr
    std::vector<std::shared_prt<Circle> >     vector_test1;
    vector_test1.push_back(std::move(pCircle1));     // Transfer ownership to vector_test1
    vector_test1.push_back(std::move(pCircle2));
    vector_test1.push_back(std::move(pCircle3));
    vector_test1.push_back(std::move(pCircle4));

    // If you don't have the latest version then
    // boost::weak_ptr
    std::vector<std::weak_ptr<Circle> >       vector_test2;
    vector_test2.push_back(vector_test1[0]);         // register an interest in the object
    vector_test2.push_back(vector_test1[1]);         // But if test1 object is destroyed
    vector_test2.push_back(vector_test1[2]);         // Then weak pointer will return NULL
    vector_test2.push_back(vector_test1[3]);

    std::vector<Circle*>::iterator itrVecTest1 = vector_test1.begin();
    std::vector<Circle*>::iterator itrVecTest1End = vector_test1.end();
    while(itrVecTest1 != itrVecTest1End)
    {
        int iType = (*itrVecTest1)->GetArea();
        if(iType ==10)
        {
            itrVecTest1.reset(NULL); // Now the pointer in vector_test2 is also gone
        }
        ++itrVecTest1;
    }
    retrun 0;
}


Why not set the objects original value to null if certain conditions are met? Then the pointer will be null as well. Doing otherwise might be a misuse of the pointer. Pointers are supposed to point to an object in memory. A pointer that doesn't point to anything doesn't seem to be the best approach.

Just my two cents. Hope this helps...


No, if you use regular pointers.

You can achieve this by creating a smart pointer class that will invalidate all pointer instances when the object is deleted. This is not difficult in C++, but it is hard to make it thread safe.

Because of this, usually smart pointers do not work that way - instead they detect when no more instances of the pointer are present, and then delete the object (a bit like garbage collection).

You may want to consider redesigning your code so that it can work with a standard smart pointer, like std::shared_ptr.


I'm not entirely sure weak_ptr would be safe to use in this context. However, you could instead use pointers to pointers.

int _tmain(int argc, _TCHAR* argv[])
{
    using std::shared_ptr; // or use boost::shared_ptr
    typedef shared_ptr<Circle> CirclePtr;
    typedef shared_ptr<CirclePtr> CirclePtrPtr;
    typedef std::vector<CirclePtrPtr> CircleList;

    CirclePtr pCircle1(new Circle(10));
    CirclePtr pCircle2(new Circle(20));
    CirclePtr pCircle3(new Circle(30));
    CirclePtr pCircle4(new Circle(40));

    CirclePtrPtr ppCircle1(new CirclePtr(pCircle1));
    CirclePtrPtr ppCircle2(new CirclePtr(pCircle2));
    CirclePtrPtr ppCircle3(new CirclePtr(pCircle3));
    CirclePtrPtr ppCircle4(new CirclePtr(pCircle4));

    CircleList vector_test1;
    vector_test1.push_back(ppCircle1);
    vector_test1.push_back(ppCircle1);
    vector_test1.push_back(ppCircle1);
    vector_test1.push_back(ppCircle1);

    CircleList vector_test2;
    vector_test2.push_back(ppCircle1);
    vector_test2.push_back(ppCircle1);
    vector_test2.push_back(ppCircle1);
    vector_test2.push_back(ppCircle1);

    for(CircleList::iterator itrVecTest1 = vector_test1.begin();
        itrVecTest1 != vector_test1.end(); ++itrVecTest1)
    {
        CirclePtr circle = *(*itrVecTest1);
        int iType = circle->GetArea();
        if(iType ==10)
        {
            circle.reset();
        }
    }

    return 0;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号