Deny std::vector from deleting its data

后端 未结 9 902
天涯浪人
天涯浪人 2021-01-17 11:03

I have the following case:

T* get_somthing(){
    std::vector vec; //T is trivally-copyable
    //fill vec
    T* temp = new T[vec.size()];
    memc         


        
相关标签:
9条回答
  • 2021-01-17 11:50

    P.S. Changing the design is not an option. Using the std::vector there is mandatory. Returning a pointer to array is also mandatory.

    Changing the design is your best option. I recommend reconsidering this stance.

    There is (currently) no way to "steal" the buffer of a vector, so given the (silly††) limitations stated in the question, copying is the way to go.

    † Tomasz Lewowski linked a proposal that would change this if it is included in a future standard: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4359.pdf (Edit: as pointed out, it was rejected from c++17)

    †† Silly until justified by concrete requirements.


    It is a wrapper between two modules. One need vector the other need pointer.

    Presumably, the other interface that needs the pointer, delegates the destruction of the buffer to the caller, possibly using some sort of call back like void delete_somthing(T*). Taking ownership without giving it back would have been very bad design, in my opinion.

    In case you do have control of the destruction, you can store the vector in a map, and erase the vector, when the pointer is passed for destruction:

    std::unordered_map<T*, std::vector<T>> storage;
    
    T* get_somthing(){
        std::vector<T> vec; //T is trivally-copyable
        //fill vec
        T* ptr = vec.data();
        storage[ptr] = std::move(vec);
        return ptr;
    }
    
    void delete_somthing(T* ptr){
        storage.erase(ptr);
    }
    
    0 讨论(0)
  • 2021-01-17 11:50

    Edit: This idea doesn't work because there is no way to prevent the implicit call to the destructors of base classes (thanks, molbdnilo). That they are called is, if I think of it, a good thing.


    I was not entirely sure whether this was viable (and curious as to what others say), but would it be possible to inherit from vector and override its destructor (to do nothing)? Even if ~vector() is not virtual (is there a requirement in the standard for being or not being virtual?) this should work as long as you explicitly use your type.

    By inheriting you would retain all the benefits, in particular the memory management -- except for the final bit (which you don't want).

    0 讨论(0)
  • 2021-01-17 11:59

    The first thing you should do is to get up, go to the one responsible for this design and (verbally in a professional manner) punch him/her in the face: It's a mess.

    Then, there's a way in C++11 to have a std::vector with automatic storage duration and have it not call its destructor:

    Put the std::vector into an union

    Like so:

    template<typename T>
    union Ugly {
      std::vector<T> vec;
      Ugly() {
        new (&vec) std::vector<T>(); // Construct
      }
      ~Ugly() {
       // Don't destruct
      }
    };
    
    T* get_something(){
      Ugly mess;
      //fill mess.vec
      return mess.vec.data();
    }
    

    I'm not 100% sure whether this still counts as valid C++11, but it should "work". Now excuse me, I need to wash my hands to get rid of the crying feeling of shame for this code ...

    Oh, and one more thing: How do you intend to release the memory that the std::vector had allocated? You know, you can't (reliably) use the pointer returned by the member function data() for that!

    0 讨论(0)
提交回复
热议问题