2

I need a class (in C++11) which stores a couple of fields(including a buffer). I started with malloc() in a constructor and free() in a destructor (I didn't touch C/C++ for quite some time so that was all I remembered).

Next thing I remembered (because of crashes) that I need to implement a copy constructor and an assignment operator. Now, I have a full screen of code just for a class with 3 fields (one of which is the buffer).

A question.

What should I use? (I am dazzled by amount of choices - std::vector, std::array, std::shared_ptr, boost::scoped_ptr and may be something else).

Functionality for this buffer which I am looking for are:

  • as little as possible memory management
  • getting rid of these copy constructors and assignment operators
  • ability to use it as void* (I have to pass it to functions which accept "void*")
  • ability to access read/write it randomly (I may need to get a random range out of it and write a random range to it)
  • allocate it on the heap (buffer can be reasonably large)
  • preferably usage of some standard facility
Victor Ronin
  • 22,758
  • 18
  • 92
  • 184
  • Do you need to be able to copy or assign your class? – Kerrek SB Nov 28 '16 at 00:36
  • 4
    Using `malloc` and `free` in C++ code is nearly always a bug. Furthermore, you cannot get "rid of these copy constructors and assignment operators". They are one of many fundamental aspects of C++. If you don't want to use them, don't use C++. – Sam Varshavchik Nov 28 '16 at 00:37
  • @KerrekSB Yes. I want to be able to copy my class. However, I hope that some smart pointer can handle it. I would prefer them sharing the pointer and counting references. However, even straight copying of the content works for me. – Victor Ronin Nov 28 '16 at 00:38
  • 2
    @SamVarshavchik Thank you. I am trying to get rid of malloc() and free() and this is exactly why I am writing this question. I was under impression that if I have smart pointers I _can_ get rid of custom copy constructors and use default ones. – Victor Ronin Nov 28 '16 at 00:40
  • 1
    No. With a dynamically-allocated object, managed by a `std::shared_ptr`, the object does not need to have any copy constructors, since it will never be copied, by definition. It won't need to have any assignment operators either, unless it is explicitly assigned to. – Sam Varshavchik Nov 28 '16 at 00:46
  • Use shared_ptr. – tukra Nov 28 '16 at 00:52
  • 3
    Will the buffer need to be resized? If so, it should probably be an `std::vector`. If not, you have more options, but the `std::vector` would save you a lot of work anyway. – Joshua Green Nov 28 '16 at 01:03
  • 2
    Why not just use std::vector? – user253751 Nov 28 '16 at 01:17
  • Well, in modern C++, you might often be able to avoid defining your own copy by selecting appropriate members... However, you have to properly determine the behavior you want. Do you want a deep copy of the array or a shared array or just moving the stuff around would be enough. If the array is large, the decision might affect performance. And in all case, the decision can affect the behavior. – Phil1970 Nov 28 '16 at 01:19
  • Since your class is only three members, a post of your class declaration, its current implementation, and the intended usage (should each object own its buffer or should it be shared, etc.) I'm guessing removing the `malloc/free` and just using `std::vector<>` for your buffer is probably a correct approach, but without more concrete information, that's all it will ever be: a guess. – WhozCraig Nov 28 '16 at 01:24

3 Answers3

5

You should just use std::vector<unsigned char> as your buffer. This already has all the necessary constructors, operators, and destructor, so there's nothing special you need to do except use it.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
0

I'm not a C++ expert, so I'd welcome any criticisms to this solution, but a smart pointer to an array might work.

#include <iostream>
#include <memory>


void do_something(void *buffer)
{
    char* char_buffer = (char*)buffer;
    std::cout << char_buffer[0] << std::endl;
}


int main()
{
    size_t size = 10;

    // reference counted pointer to auto-delete the buffer
    std::shared_ptr<char> buffer(new char[size], std::default_delete<char[]>());

    // use the underlying pointer
    // http://stackoverflow.com/questions/27819809/why-is-there-no-operator-for-stdshared-ptr
    buffer.get()[0] = 'a';

    do_something(buffer.get());
    // buffer deallocated at the end of scope
}
  • as little as possible memory management

The smart pointer takes care of that for you

  • getting rid of these copy constructors and assignment operators

I think the smart pointer handles them

  • ability to use it as void* (I have to pass it to functions which accept "void*")

Use .get() and a cast.

  • ability to access read/write it randomly (I may need to get a random range out of it and write a random range to it)

It's still a pointer at the end of this, so I can't see why that wouldn't work (I haven't tried it).

  • allocate it on the heap (buffer can be reasonably large)

It's on the heap

  • preferably usage of some standard facility

<memory>

Alternatively, checkout <vector>'s .data() function, which returns a pointer to the vector's underlying array.

Ben
  • 5,952
  • 4
  • 33
  • 44
0

I think you need some kind of memory buffer. Check this simple c++ buffer class. Not using c++11 is intentional because of my company development environment.
https://github.com/jeremyko/CumBuffer

jeremyko
  • 408
  • 5
  • 8