Destroy std::vector without releasing memory

前端 未结 2 1308
-上瘾入骨i
-上瘾入骨i 2021-02-20 11:16

Lets say I have a function to get data into an std vector:

void getData(std::vector &toBeFilled) {
  // Push data into \"toBeFilled\"
}

2条回答
  •  难免孤独
    2021-02-20 12:01

    Here's a horrible hack which should allow you to do what you need, but it relies on Undefined Behaviour doing the simplest thing it can. The idea is to create your own allocator which is layout-compatible with std::allocator and type-pun the vector:

    template 
    struct CheatingAllocator : std::allocator
    {
      using typename std::allocator::pointer;
      using typename std::allocator::size_type;
    
      void deallocate(pointer p, size_type n) { /* no-op */ }
    
      // Do not add ANY data members!!
    };
    
    
    {
      std::vector> data;
      getData(reinterpret_cast&>(data)); // type pun, `getData()` will use std::allocator internally
      useData(data.data());
      // data actually uses your own allocator, so it will not deallocate anything
    }
    

    Note that it's as hacky and unsafe as hacks go. It relies on the memory layout not changing and it relies of std::allocator using new[] inside its allocate function. I wouldn't use this in production code myself, but I believe it is a (desperate) solution.


    @TonyD correctly pointed out in the comments that std::allocator is quite likely to not use new[] internally. Therefore, the above would most likely fail on the delete[] inside useData(). The same @TonyD also made a good point about using reserve() to (hopefully) prevent reallocation inside getData(). So the updated code would look like this:

    template 
    struct CheatingAllocator : std::allocator
    {
      using typename std::allocator::pointer;
      using typename std::allocator::size_type;
    
      pointer allocate(size_type n) { return new T[n]; }
    
      void deallocate(pointer p, size_type n) { /* no-op */ }
    
      // Do not add ANY data members!!
    };
    
    
    {
      std::vector> data;
      data.reserve(value_such_that_getData_will_not_need_to_reallocate);
      getData(reinterpret_cast&>(data)); // type pun, `getData()` will use std::allocator internally
      useData(data.data());
      // data actually uses your own allocator, so it will not deallocate anything
    }
    

提交回复
热议问题