In Which Situations To Delete A Pointer

后端 未结 5 1926
深忆病人
深忆病人 2021-01-17 10:55

My following question is on memory management. I have for example an int variable not allocated dynamically in a class, let\'s say invar1. And I\'m passing the memory addres

5条回答
  •  生来不讨喜
    2021-01-17 10:59

    You don't currently delete this int, or show where it's allocated. If neither object is supposed to own its parameter, I'd write

    struct ex1 {
        ex1(int &i_) : i(i_) {}
        int &i;               // reference implies no ownership
    };
    struct ex2 {
        ex2(ex1 &e_) : e(e_) {}
        ex1 &e;               // reference implies no ownership
    };
    
    int i = 42;
    ex1 a(i);
    ex2 b(a);
    

    If either argument is supposed to be owned by the new object, pass it as a unique_ptr. If either argument is supposed to be shared, use shared_ptr. I'd generally prefer any of these (reference or smart pointer) to raw pointers, because they give more information about your intentions.


    In general, to make these decisions,

    Should I delete ptoint?

    is the wrong question. First consider things at a slightly higher level:

    1. what does this int represent in your program?
    2. who, if anyone, owns it?
    3. how long is it supposed to live, compared to these classes that use it?

    and then see how the answer falls out naturally for these examples:

    • this int is an I/O mapped control register.

      In this case it wasn't created with new (it exists outside your whole program), and therefore you certainly shouldn't delete it. It should probably also be marked volatile, but that doesn't affect lifetime.

      Maybe something outside your class mapped the address and should also unmap it, which is loosely analogous to (de)allocating it, or maybe it's simply a well-known address.

    • this int is a global logging level.

      In this case it presumably has either static lifetime, in which case no-one owns it, it was not explicitly allocated and therefore should not be explicitly de-allocated

      or, it's owned by a logger object/singleton/mock/whatever, and that object is responsible for deallocating it if necessary

    • this int is being explicitly given to your object to own

      In this case, it's good practice to make that obvious, eg.

      ex1::ex1(std::unique_ptr &&p) : m_p(std::move(p)) {}
      

      Note that making your local data member a unique_ptr or similar, also takes care of the lifetime automatically with no effort on your part.

    • this int is being given to your object to use, but other objects may also be using it, and it isn't obvious which order they will finish in.

      Use a shared_ptr instead of unique_ptr to describe this relationship. Again, the smart pointer will manage the lifetime for you.

    In general, if you can encode the ownership and lifetime information in the type, you don't need to remember where to manually allocate and deallocate things. This is much clearer and safer.

    If you can't encode that information in the type, you can at least be clear about your intentions: the fact that you ask about deallocation without mentioning lifetime or ownership, suggests you're working at the wrong level of abstraction.

提交回复
热议问题