【问题标题】:Set pointer to null将指针设置为空
【发布时间】:2011-07-18 17:14:15
【问题描述】:

在我的 c++ 应用程序中,我创建了一些指向对象的指针并将它们添加到两个向量中。然后我遍历一个向量,直到找到一个满足所需条件的对象。如果它满意,我想将该指针设为 NULL。最主要的是我想在所有地方都将其设为 NULL。示例代码如下。

   #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 _tmain(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;
}

这里 pCircle1 满足给定条件,我想从所有地方删除它。使用此代码,我可以使 vector_test1 中的指针为空。但是有没有一种方法可以同时在 vector_test2 中设置相同的指针而无需遍历它?

【问题讨论】:

  • 也许你应该重新评估你想要做什么。为什么你必须使用指针?另请注意,此代码泄漏,例如:Circle* pCircle1 = new Circle(10); Circle* pCircle2 = new Circle(20);,如果 new Circle(20); 抛出然后指向 pCircle1 的内存将被泄漏。此外,pCircle2 .. 4 中的任何一个都不会在任何执行路径中释放。

标签: c++


【解决方案1】:

是的,使用弱指针。

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;
}

【讨论】:

    【解决方案2】:

    如果满足某些条件,为什么不将对象的原始值设置为 null?然后指针也将为空。否则可能会滥用指针。指针应该指向内存中的对象。不指向任何东西的指针似乎不是最好的方法。

    只有我的两分钱。希望这会有所帮助...

    【讨论】:

    • 真的,上面发布的代码是我实际代码的简化版本。在实际代码中,我创建了对象指针并将它们推送到一个地方的向量,然后在另一个地方我检查条件以删除一些要从向量中删除的对象。这就是为什么我不能将对象的原始值设置为 null。
    【解决方案3】:

    不,如果您使用常规指针。

    您可以通过创建一个智能指针类来实现这一点,该类将在删除对象时使所有指针实例无效。这在 C++ 中并不难,但很难使其成为线程安全的。

    因此,智能指针通常不会以这种方式工作 - 相反,它们会检测何时不再存在指针实例,然后删除对象(有点像垃圾收集)。

    您可能需要考虑重新设计您的代码,以便它可以使用标准智能指针,例如 std::shared_ptr。

    【讨论】:

    • 非常感谢您的回答。我对指针概念真的很陌生。所以所有的答案都非常有帮助。但我仍然想知道一件事。我在一个地方创建了一个指针并将其添加到多个向量中。为什么我不能在一个地方删除它,即使我在一个地方创建它???
    • @coders:不要将指针与其指向的对象混淆。 new Circle(10) 创建一个 Circle 对象,并给你它的地址。您将该地址复制到两个不同的向量中。向量包含 每个 包含一个指针,具有相同的值(即指向同一个对象)。您可以在一个地方销毁 object,这与找到指向该对象的所有不同指针完全不同。打个比方:你可以取消你的手机合约,但你所有的朋友的手机里都会有旧号码。数字(或指针)只是一个地址。
    • 太棒了 :) 解释得很好。非常感谢
    【解决方案4】:

    我不完全确定在这种情况下使用 weak_ptr 是否安全。但是,您可以改为使用指向指针的指针。

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 2017-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-24
      • 2018-10-02
      • 1970-01-01
      • 2016-06-16
      相关资源
      最近更新 更多