tags:

views:

126

answers:

2

I create many times I use class DataBuffer in many places in code, so it should be fast and lightweight. Moreover I use various buffer sizes, so to reduce memory allocations I wrote such template:

template<unsigned int T_buffer_size> class DataBuffer
{
    public:
        DataBuffer (const unsigned int &buffer_size);

        char buffer [T_buffer_size];
        const unsigned int buffer_size;
};

The problem is, that i have to copy DataBuffer objects few times. That's why I'm wondering if move constructor can help here. Is there an easy way to move my 'buffer' array between objects?

It's easy to implement this class:

class DataBuffer
{
    public:
        DataBuffer (const unsigned int &buffer_size);

        char *buffer;
        const unsigned int buffer_size;
};

But because 'buffer' is a regular pointer it takes more time to access data stored inside it...

+2  A: 

Is there an easy way to move my 'buffer' array between objects* (char buffer [T_buffer_size];)?

No, you have to copy (althrough you can safely use memcpy(...) which is pretty fast) as its allocated on the stack, and not a pointer. Only pointers/objects allocated on the heap, can take advantage of the rvalue optimization.

Update: Looking at the code, you can rewrite it as:

template<unsigned int T_buffer_size> class DataBuffer
{
    public:
        DataBuffer ();
        char buffer [T_buffer_size];
};
Viktor Sehr
It's not allocated on the stack (necessarily), it's inside the class. So it uses whatever allocator was used for the class instance.
Ben Voigt
Ben: lets say it's STAtiCKally allocated
Viktor Sehr
+1  A: 

But because 'buffer' is a regular pointer it takes more time to access data stored inside it...

I think you're mistaken. Accessing an array on the heap is not necessarily slower than accessing one on the stack, e.g. The real difference will be in creating and destroying the array.

You can't really have it both ways, directly speaking (but do read further). If your DataBuffer allocates on the heap, it will pay the price for the overhead of heap-based allocation and deallocation, but you will be able to shallow swap the data and implement something like a move constructor (see Alexandrescu's mojo as a simple proposal to the problem). If it allocates data on the stack, then it will be very fast to create and destroy, but will have to deep copy data which can be a bit expensive (though memcpy is awfully fast and perfectly fine for a char buffer).

However, you can get the best of both worlds by writing your own memory allocator. I only recommend doing this if you really want to put the effort into it and have seen, with the aid of the profiler, that this is a real bottleneck. I don't have the time or room to teach you this here, but I must warn you that it is not as trivial as it seems to write one (consider alignment as an example).

The determination of whether you go for the first example or the second should primarily be dictated by whether you can always determine the buffer size at compile time. If so, go for the first solution as it allows the buffer to be allocated on the stack or the heap. You can still shallow swap data by doing:

DataBuffer<some_size>* d1 = new DataBuffer<some_size>; 
DataBuffer<some_size>* d2 = 0; 
std::swap(d1, d2);

... or for more sophisticated examples, you can use things like boost::shared_ptr.