Elegant Circular Buffer











up vote
4
down vote

favorite
1












I would like to design an elegant yet efficient circular buffer of integers.
I have designed a FIFO type circular buffer in C++(11)- starting with the class header (declaration) as follow:



[cyclicBuffer.hpp]:



#ifndef __CyclicBuff_HPP
#define __CyclicBuff_HPP
#pragma once

class CyclicBuffer
{
public:
CyclicBuffer(int buffSize);
~CyclicBuffer();
void setChar(char c);
char getChar();
void clearCycBuff(int buffSize);
private:
char *buffer;
int bufferSize;
int head; // index for the top of the buffer
int tail; // indes for the bottom of the buffer
};

#endif


implementation of the class is as following:
[cyclicBuffer.cpp]:



#include "stdafx.h"
#include "cyclicBuffer.hpp"
#include <iostream>

//using namespace std;

CyclicBuffer::CyclicBuffer(int buffSize)
{
head = 0;
tail = 0;
bufferSize = buffSize;
buffer = new char[bufferSize];
std::cout << "Buffer initated successfullyn";

/*
{
std::cout << "Buffer was not createdn driver exiting...n";
// return -1;
}*/
}

CyclicBuffer::~CyclicBuffer()
{
delete buffer;
std::cout << "Buffer destroyed successfullyn";
}


void CyclicBuffer::clearCycBuff(int buffSize) //not used , has no meaning to set '0'

{
head = 0;
tail = 0;
for (int i = 0; i <= buffSize; i++)
buffer[i] = '0';
}

void CyclicBuffer::setChar(char c)
{
//std::cout << "head: " << head << 'n';
head %= bufferSize;
buffer[head] = c;
head++;
}

char CyclicBuffer::getChar(void)
{
//std::cout << " tail:" << tail<<'n';
tail %= bufferSize;
return buffer[tail++];

}


Finally, testing the class by an instance as follow:



// CyclicBufferMain.cpp : Defines the entry point for the console 
// application.


#include "stdafx.h"
#include <iostream>
#include "cyclicBuffer.hpp"

#define SIZE 32

int main(void)
{
CyclicBuffer aBuffer(SIZE);

for (int i = 0; i < SIZE*1.5; i++)
aBuffer.setChar((char)(i+45));

for (int i = 0; i < SIZE ; i++)
std::cout << aBuffer.getChar() << ' ';


std::cout << 'n';



return 0;
}


for the given main function the result will be like this:
enter image description here



My question: is this class is efficient enough for low-rate uC ? (targeting to Atmel, RISC type or low performance ARM uC)



Regarding @Toby Speight: Thanks for your helpful comments and advices - few questions for you:



(1) when I did delete instead delete , did I make a 'memory leak'? why MS VStudio (2015) didn't warn me?



(2) I would change the CyclicBuffer::clearCycBuff() member function to use buffer[i] = 0; (instead buffer[i]='0';) to clear the buffer's values.



(3) Why need to drop the commented-out code?



(4) You used uniform initializer at the constructor - is it big difference as to what I did using regular variable assignments at the constructor ?



(5) I know 'size_t' is it a specialize typedef that exists at the GNU and MS compilers but would have a problem using it when porting the code to a specific target which could not have such typedef ?



Thanks.










share|improve this question















migrated from stackoverflow.com May 24 '17 at 20:08


This question came from our site for professional and enthusiast programmers.











  • 2




    I have usually found an additional value to be necessary: the number of items in the buffer, because when the index head == tail you cannot know whether a circular buffer is empty or full.
    – Weather Vane
    May 24 '17 at 19:44






  • 1




    ... and sweeter, because you don't need to be continually making a (head - tail + size) % size calculation to determine how many items there are in the buffer.
    – Weather Vane
    May 24 '17 at 19:53






  • 2




    The most heavy operation in your actual code is taking the remainder. Its performance varies target-wise, and you might find some performance gain by switching it to comparison with the container size. Also, restricting the possible buffer sizes to the power of two will allow you to substitute the division with bitwise and.
    – iehrlich
    May 24 '17 at 19:53






  • 2




    Also, you don't need both include guards and #pragma once.
    – iehrlich
    May 24 '17 at 19:54






  • 2




    Don't forget to change your delete to delete
    – Ceros
    May 24 '17 at 21:25















up vote
4
down vote

favorite
1












I would like to design an elegant yet efficient circular buffer of integers.
I have designed a FIFO type circular buffer in C++(11)- starting with the class header (declaration) as follow:



[cyclicBuffer.hpp]:



#ifndef __CyclicBuff_HPP
#define __CyclicBuff_HPP
#pragma once

class CyclicBuffer
{
public:
CyclicBuffer(int buffSize);
~CyclicBuffer();
void setChar(char c);
char getChar();
void clearCycBuff(int buffSize);
private:
char *buffer;
int bufferSize;
int head; // index for the top of the buffer
int tail; // indes for the bottom of the buffer
};

#endif


implementation of the class is as following:
[cyclicBuffer.cpp]:



#include "stdafx.h"
#include "cyclicBuffer.hpp"
#include <iostream>

//using namespace std;

CyclicBuffer::CyclicBuffer(int buffSize)
{
head = 0;
tail = 0;
bufferSize = buffSize;
buffer = new char[bufferSize];
std::cout << "Buffer initated successfullyn";

/*
{
std::cout << "Buffer was not createdn driver exiting...n";
// return -1;
}*/
}

CyclicBuffer::~CyclicBuffer()
{
delete buffer;
std::cout << "Buffer destroyed successfullyn";
}


void CyclicBuffer::clearCycBuff(int buffSize) //not used , has no meaning to set '0'

{
head = 0;
tail = 0;
for (int i = 0; i <= buffSize; i++)
buffer[i] = '0';
}

void CyclicBuffer::setChar(char c)
{
//std::cout << "head: " << head << 'n';
head %= bufferSize;
buffer[head] = c;
head++;
}

char CyclicBuffer::getChar(void)
{
//std::cout << " tail:" << tail<<'n';
tail %= bufferSize;
return buffer[tail++];

}


Finally, testing the class by an instance as follow:



// CyclicBufferMain.cpp : Defines the entry point for the console 
// application.


#include "stdafx.h"
#include <iostream>
#include "cyclicBuffer.hpp"

#define SIZE 32

int main(void)
{
CyclicBuffer aBuffer(SIZE);

for (int i = 0; i < SIZE*1.5; i++)
aBuffer.setChar((char)(i+45));

for (int i = 0; i < SIZE ; i++)
std::cout << aBuffer.getChar() << ' ';


std::cout << 'n';



return 0;
}


for the given main function the result will be like this:
enter image description here



My question: is this class is efficient enough for low-rate uC ? (targeting to Atmel, RISC type or low performance ARM uC)



Regarding @Toby Speight: Thanks for your helpful comments and advices - few questions for you:



(1) when I did delete instead delete , did I make a 'memory leak'? why MS VStudio (2015) didn't warn me?



(2) I would change the CyclicBuffer::clearCycBuff() member function to use buffer[i] = 0; (instead buffer[i]='0';) to clear the buffer's values.



(3) Why need to drop the commented-out code?



(4) You used uniform initializer at the constructor - is it big difference as to what I did using regular variable assignments at the constructor ?



(5) I know 'size_t' is it a specialize typedef that exists at the GNU and MS compilers but would have a problem using it when porting the code to a specific target which could not have such typedef ?



Thanks.










share|improve this question















migrated from stackoverflow.com May 24 '17 at 20:08


This question came from our site for professional and enthusiast programmers.











  • 2




    I have usually found an additional value to be necessary: the number of items in the buffer, because when the index head == tail you cannot know whether a circular buffer is empty or full.
    – Weather Vane
    May 24 '17 at 19:44






  • 1




    ... and sweeter, because you don't need to be continually making a (head - tail + size) % size calculation to determine how many items there are in the buffer.
    – Weather Vane
    May 24 '17 at 19:53






  • 2




    The most heavy operation in your actual code is taking the remainder. Its performance varies target-wise, and you might find some performance gain by switching it to comparison with the container size. Also, restricting the possible buffer sizes to the power of two will allow you to substitute the division with bitwise and.
    – iehrlich
    May 24 '17 at 19:53






  • 2




    Also, you don't need both include guards and #pragma once.
    – iehrlich
    May 24 '17 at 19:54






  • 2




    Don't forget to change your delete to delete
    – Ceros
    May 24 '17 at 21:25













up vote
4
down vote

favorite
1









up vote
4
down vote

favorite
1






1





I would like to design an elegant yet efficient circular buffer of integers.
I have designed a FIFO type circular buffer in C++(11)- starting with the class header (declaration) as follow:



[cyclicBuffer.hpp]:



#ifndef __CyclicBuff_HPP
#define __CyclicBuff_HPP
#pragma once

class CyclicBuffer
{
public:
CyclicBuffer(int buffSize);
~CyclicBuffer();
void setChar(char c);
char getChar();
void clearCycBuff(int buffSize);
private:
char *buffer;
int bufferSize;
int head; // index for the top of the buffer
int tail; // indes for the bottom of the buffer
};

#endif


implementation of the class is as following:
[cyclicBuffer.cpp]:



#include "stdafx.h"
#include "cyclicBuffer.hpp"
#include <iostream>

//using namespace std;

CyclicBuffer::CyclicBuffer(int buffSize)
{
head = 0;
tail = 0;
bufferSize = buffSize;
buffer = new char[bufferSize];
std::cout << "Buffer initated successfullyn";

/*
{
std::cout << "Buffer was not createdn driver exiting...n";
// return -1;
}*/
}

CyclicBuffer::~CyclicBuffer()
{
delete buffer;
std::cout << "Buffer destroyed successfullyn";
}


void CyclicBuffer::clearCycBuff(int buffSize) //not used , has no meaning to set '0'

{
head = 0;
tail = 0;
for (int i = 0; i <= buffSize; i++)
buffer[i] = '0';
}

void CyclicBuffer::setChar(char c)
{
//std::cout << "head: " << head << 'n';
head %= bufferSize;
buffer[head] = c;
head++;
}

char CyclicBuffer::getChar(void)
{
//std::cout << " tail:" << tail<<'n';
tail %= bufferSize;
return buffer[tail++];

}


Finally, testing the class by an instance as follow:



// CyclicBufferMain.cpp : Defines the entry point for the console 
// application.


#include "stdafx.h"
#include <iostream>
#include "cyclicBuffer.hpp"

#define SIZE 32

int main(void)
{
CyclicBuffer aBuffer(SIZE);

for (int i = 0; i < SIZE*1.5; i++)
aBuffer.setChar((char)(i+45));

for (int i = 0; i < SIZE ; i++)
std::cout << aBuffer.getChar() << ' ';


std::cout << 'n';



return 0;
}


for the given main function the result will be like this:
enter image description here



My question: is this class is efficient enough for low-rate uC ? (targeting to Atmel, RISC type or low performance ARM uC)



Regarding @Toby Speight: Thanks for your helpful comments and advices - few questions for you:



(1) when I did delete instead delete , did I make a 'memory leak'? why MS VStudio (2015) didn't warn me?



(2) I would change the CyclicBuffer::clearCycBuff() member function to use buffer[i] = 0; (instead buffer[i]='0';) to clear the buffer's values.



(3) Why need to drop the commented-out code?



(4) You used uniform initializer at the constructor - is it big difference as to what I did using regular variable assignments at the constructor ?



(5) I know 'size_t' is it a specialize typedef that exists at the GNU and MS compilers but would have a problem using it when porting the code to a specific target which could not have such typedef ?



Thanks.










share|improve this question















I would like to design an elegant yet efficient circular buffer of integers.
I have designed a FIFO type circular buffer in C++(11)- starting with the class header (declaration) as follow:



[cyclicBuffer.hpp]:



#ifndef __CyclicBuff_HPP
#define __CyclicBuff_HPP
#pragma once

class CyclicBuffer
{
public:
CyclicBuffer(int buffSize);
~CyclicBuffer();
void setChar(char c);
char getChar();
void clearCycBuff(int buffSize);
private:
char *buffer;
int bufferSize;
int head; // index for the top of the buffer
int tail; // indes for the bottom of the buffer
};

#endif


implementation of the class is as following:
[cyclicBuffer.cpp]:



#include "stdafx.h"
#include "cyclicBuffer.hpp"
#include <iostream>

//using namespace std;

CyclicBuffer::CyclicBuffer(int buffSize)
{
head = 0;
tail = 0;
bufferSize = buffSize;
buffer = new char[bufferSize];
std::cout << "Buffer initated successfullyn";

/*
{
std::cout << "Buffer was not createdn driver exiting...n";
// return -1;
}*/
}

CyclicBuffer::~CyclicBuffer()
{
delete buffer;
std::cout << "Buffer destroyed successfullyn";
}


void CyclicBuffer::clearCycBuff(int buffSize) //not used , has no meaning to set '0'

{
head = 0;
tail = 0;
for (int i = 0; i <= buffSize; i++)
buffer[i] = '0';
}

void CyclicBuffer::setChar(char c)
{
//std::cout << "head: " << head << 'n';
head %= bufferSize;
buffer[head] = c;
head++;
}

char CyclicBuffer::getChar(void)
{
//std::cout << " tail:" << tail<<'n';
tail %= bufferSize;
return buffer[tail++];

}


Finally, testing the class by an instance as follow:



// CyclicBufferMain.cpp : Defines the entry point for the console 
// application.


#include "stdafx.h"
#include <iostream>
#include "cyclicBuffer.hpp"

#define SIZE 32

int main(void)
{
CyclicBuffer aBuffer(SIZE);

for (int i = 0; i < SIZE*1.5; i++)
aBuffer.setChar((char)(i+45));

for (int i = 0; i < SIZE ; i++)
std::cout << aBuffer.getChar() << ' ';


std::cout << 'n';



return 0;
}


for the given main function the result will be like this:
enter image description here



My question: is this class is efficient enough for low-rate uC ? (targeting to Atmel, RISC type or low performance ARM uC)



Regarding @Toby Speight: Thanks for your helpful comments and advices - few questions for you:



(1) when I did delete instead delete , did I make a 'memory leak'? why MS VStudio (2015) didn't warn me?



(2) I would change the CyclicBuffer::clearCycBuff() member function to use buffer[i] = 0; (instead buffer[i]='0';) to clear the buffer's values.



(3) Why need to drop the commented-out code?



(4) You used uniform initializer at the constructor - is it big difference as to what I did using regular variable assignments at the constructor ?



(5) I know 'size_t' is it a specialize typedef that exists at the GNU and MS compilers but would have a problem using it when porting the code to a specific target which could not have such typedef ?



Thanks.







c++ circular-list embedded






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 12 at 12:49









Mathias Ettinger

23k33177




23k33177










asked May 24 '17 at 19:36









Itzik Chaimov

235




235




migrated from stackoverflow.com May 24 '17 at 20:08


This question came from our site for professional and enthusiast programmers.






migrated from stackoverflow.com May 24 '17 at 20:08


This question came from our site for professional and enthusiast programmers.










  • 2




    I have usually found an additional value to be necessary: the number of items in the buffer, because when the index head == tail you cannot know whether a circular buffer is empty or full.
    – Weather Vane
    May 24 '17 at 19:44






  • 1




    ... and sweeter, because you don't need to be continually making a (head - tail + size) % size calculation to determine how many items there are in the buffer.
    – Weather Vane
    May 24 '17 at 19:53






  • 2




    The most heavy operation in your actual code is taking the remainder. Its performance varies target-wise, and you might find some performance gain by switching it to comparison with the container size. Also, restricting the possible buffer sizes to the power of two will allow you to substitute the division with bitwise and.
    – iehrlich
    May 24 '17 at 19:53






  • 2




    Also, you don't need both include guards and #pragma once.
    – iehrlich
    May 24 '17 at 19:54






  • 2




    Don't forget to change your delete to delete
    – Ceros
    May 24 '17 at 21:25














  • 2




    I have usually found an additional value to be necessary: the number of items in the buffer, because when the index head == tail you cannot know whether a circular buffer is empty or full.
    – Weather Vane
    May 24 '17 at 19:44






  • 1




    ... and sweeter, because you don't need to be continually making a (head - tail + size) % size calculation to determine how many items there are in the buffer.
    – Weather Vane
    May 24 '17 at 19:53






  • 2




    The most heavy operation in your actual code is taking the remainder. Its performance varies target-wise, and you might find some performance gain by switching it to comparison with the container size. Also, restricting the possible buffer sizes to the power of two will allow you to substitute the division with bitwise and.
    – iehrlich
    May 24 '17 at 19:53






  • 2




    Also, you don't need both include guards and #pragma once.
    – iehrlich
    May 24 '17 at 19:54






  • 2




    Don't forget to change your delete to delete
    – Ceros
    May 24 '17 at 21:25








2




2




I have usually found an additional value to be necessary: the number of items in the buffer, because when the index head == tail you cannot know whether a circular buffer is empty or full.
– Weather Vane
May 24 '17 at 19:44




I have usually found an additional value to be necessary: the number of items in the buffer, because when the index head == tail you cannot know whether a circular buffer is empty or full.
– Weather Vane
May 24 '17 at 19:44




1




1




... and sweeter, because you don't need to be continually making a (head - tail + size) % size calculation to determine how many items there are in the buffer.
– Weather Vane
May 24 '17 at 19:53




... and sweeter, because you don't need to be continually making a (head - tail + size) % size calculation to determine how many items there are in the buffer.
– Weather Vane
May 24 '17 at 19:53




2




2




The most heavy operation in your actual code is taking the remainder. Its performance varies target-wise, and you might find some performance gain by switching it to comparison with the container size. Also, restricting the possible buffer sizes to the power of two will allow you to substitute the division with bitwise and.
– iehrlich
May 24 '17 at 19:53




The most heavy operation in your actual code is taking the remainder. Its performance varies target-wise, and you might find some performance gain by switching it to comparison with the container size. Also, restricting the possible buffer sizes to the power of two will allow you to substitute the division with bitwise and.
– iehrlich
May 24 '17 at 19:53




2




2




Also, you don't need both include guards and #pragma once.
– iehrlich
May 24 '17 at 19:54




Also, you don't need both include guards and #pragma once.
– iehrlich
May 24 '17 at 19:54




2




2




Don't forget to change your delete to delete
– Ceros
May 24 '17 at 21:25




Don't forget to change your delete to delete
– Ceros
May 24 '17 at 21:25










2 Answers
2






active

oldest

votes

















up vote
3
down vote



accepted










Improve the wrap-around logic



There's obvious inefficiency in:



head %= bufferSize;


% uses division, but because we're incrementing, we know that head / bufferSize is at most 1. Instead, we can:



if (++head >= bufferSize)
head -= bufferSize;


On architectures such as ARM, there's no branch here, as any decent compiler will just use a condition flag on the subtraction.





Consider checking for overrun and underrun



At the moment, this buffer has no checking for the read and write positions crossing each other. Perhaps that's what you need, but it's quite unusual to have an unchecked circular buffer, and if you were holding (e.g.) audio data, you can imagine how it would sound, given the output you show.





Match new and delete



Since you create buffer using new, you must use the array form delete in the destructor:



CyclicBuffer::~CyclicBuffer()
{
delete buffer;
}




Style points



Prefer initializers to assignment



A constructor should initialize all the members of the class:



CyclicBuffer::CyclicBuffer(std::size_t buffSize)
: buffer(new char[bufferSize]),
bufferSize(buffSize),
head(0),
tail(0)
{
}


A good compiler will warn you if you have uninitialized members (e.g. g++ -Wall -Wextra).



Note that I've also changed the argument to be a size_t, as a negative size is meaningless. The int members should all be size_t, too.



Avoid numeric character constants



What's special about the number 45? If you care about its character value, (and if you're using an ASCII-like system), it's clearer to write '-' instead.



Drop the commented-out code



I don't want to see using std::namespace;, ever. Not even in a comment.






share|improve this answer























  • Regarding the suggested fix about % division, since it is always incrementing, we can put if (++head >= bufferSize) head = 0; right? And it should be more efficient as we are avoiding the subtraction. Am I missing something here?
    – Anubis
    Jun 28 at 10:55












  • No, you're missing nothing - assigning zero is less work than subtraction, and would be a further improvement.
    – Toby Speight
    Jul 4 at 7:20






  • 2




    @TobySpeight : In fact, // is the best prefix for using namespace std;
    – Calak
    Nov 12 at 14:57


















up vote
0
down vote













Constructor initialization - 0 out the array



buffer(new T[size]{}) will set all the values to 0 instead of random garbage



template<class T>
CyclicBuffer<T>::CyclicBuffer(std::size_t size): head(0), tail(0), buffer(new T[size]{}), size(size) {

}


Adding and Getting can use equality comparison



Comparing equality rather than subtracting/greater or equals makes it more readable





template<class T>
void CyclicBuffer<T>::add(T val) {
if (head == size)
head = 0;

buffer[head++] = val;
}

template<class T>
T CyclicBuffer<T>::get() {
if (tail == size)
tail = 0;

return buffer[tail++];
}


Use template to make your structure generic



You will be able to insert any type:



CyclicBuffer<char> charCyclicBuffer(5);
CyclicBuffer<int> intCyclicBuffer(5);


Use std::size_t for portability



Besides portability - size, head, tail will never be negative



template<class T>
class CyclicBuffer{
public:
explicit CyclicBuffer(std::size_t size);

~CyclicBuffer();

void add(T val);

T get();

inline std::size_t getSize() {
return this->size;
}

private:
T *buffer;
std::size_t size;
std::size_t head;
std::size_t tail;
};





share|improve this answer








New contributor




Eugene Barnett is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


















    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f164130%2felegant-circular-buffer%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    3
    down vote



    accepted










    Improve the wrap-around logic



    There's obvious inefficiency in:



    head %= bufferSize;


    % uses division, but because we're incrementing, we know that head / bufferSize is at most 1. Instead, we can:



    if (++head >= bufferSize)
    head -= bufferSize;


    On architectures such as ARM, there's no branch here, as any decent compiler will just use a condition flag on the subtraction.





    Consider checking for overrun and underrun



    At the moment, this buffer has no checking for the read and write positions crossing each other. Perhaps that's what you need, but it's quite unusual to have an unchecked circular buffer, and if you were holding (e.g.) audio data, you can imagine how it would sound, given the output you show.





    Match new and delete



    Since you create buffer using new, you must use the array form delete in the destructor:



    CyclicBuffer::~CyclicBuffer()
    {
    delete buffer;
    }




    Style points



    Prefer initializers to assignment



    A constructor should initialize all the members of the class:



    CyclicBuffer::CyclicBuffer(std::size_t buffSize)
    : buffer(new char[bufferSize]),
    bufferSize(buffSize),
    head(0),
    tail(0)
    {
    }


    A good compiler will warn you if you have uninitialized members (e.g. g++ -Wall -Wextra).



    Note that I've also changed the argument to be a size_t, as a negative size is meaningless. The int members should all be size_t, too.



    Avoid numeric character constants



    What's special about the number 45? If you care about its character value, (and if you're using an ASCII-like system), it's clearer to write '-' instead.



    Drop the commented-out code



    I don't want to see using std::namespace;, ever. Not even in a comment.






    share|improve this answer























    • Regarding the suggested fix about % division, since it is always incrementing, we can put if (++head >= bufferSize) head = 0; right? And it should be more efficient as we are avoiding the subtraction. Am I missing something here?
      – Anubis
      Jun 28 at 10:55












    • No, you're missing nothing - assigning zero is less work than subtraction, and would be a further improvement.
      – Toby Speight
      Jul 4 at 7:20






    • 2




      @TobySpeight : In fact, // is the best prefix for using namespace std;
      – Calak
      Nov 12 at 14:57















    up vote
    3
    down vote



    accepted










    Improve the wrap-around logic



    There's obvious inefficiency in:



    head %= bufferSize;


    % uses division, but because we're incrementing, we know that head / bufferSize is at most 1. Instead, we can:



    if (++head >= bufferSize)
    head -= bufferSize;


    On architectures such as ARM, there's no branch here, as any decent compiler will just use a condition flag on the subtraction.





    Consider checking for overrun and underrun



    At the moment, this buffer has no checking for the read and write positions crossing each other. Perhaps that's what you need, but it's quite unusual to have an unchecked circular buffer, and if you were holding (e.g.) audio data, you can imagine how it would sound, given the output you show.





    Match new and delete



    Since you create buffer using new, you must use the array form delete in the destructor:



    CyclicBuffer::~CyclicBuffer()
    {
    delete buffer;
    }




    Style points



    Prefer initializers to assignment



    A constructor should initialize all the members of the class:



    CyclicBuffer::CyclicBuffer(std::size_t buffSize)
    : buffer(new char[bufferSize]),
    bufferSize(buffSize),
    head(0),
    tail(0)
    {
    }


    A good compiler will warn you if you have uninitialized members (e.g. g++ -Wall -Wextra).



    Note that I've also changed the argument to be a size_t, as a negative size is meaningless. The int members should all be size_t, too.



    Avoid numeric character constants



    What's special about the number 45? If you care about its character value, (and if you're using an ASCII-like system), it's clearer to write '-' instead.



    Drop the commented-out code



    I don't want to see using std::namespace;, ever. Not even in a comment.






    share|improve this answer























    • Regarding the suggested fix about % division, since it is always incrementing, we can put if (++head >= bufferSize) head = 0; right? And it should be more efficient as we are avoiding the subtraction. Am I missing something here?
      – Anubis
      Jun 28 at 10:55












    • No, you're missing nothing - assigning zero is less work than subtraction, and would be a further improvement.
      – Toby Speight
      Jul 4 at 7:20






    • 2




      @TobySpeight : In fact, // is the best prefix for using namespace std;
      – Calak
      Nov 12 at 14:57













    up vote
    3
    down vote



    accepted







    up vote
    3
    down vote



    accepted






    Improve the wrap-around logic



    There's obvious inefficiency in:



    head %= bufferSize;


    % uses division, but because we're incrementing, we know that head / bufferSize is at most 1. Instead, we can:



    if (++head >= bufferSize)
    head -= bufferSize;


    On architectures such as ARM, there's no branch here, as any decent compiler will just use a condition flag on the subtraction.





    Consider checking for overrun and underrun



    At the moment, this buffer has no checking for the read and write positions crossing each other. Perhaps that's what you need, but it's quite unusual to have an unchecked circular buffer, and if you were holding (e.g.) audio data, you can imagine how it would sound, given the output you show.





    Match new and delete



    Since you create buffer using new, you must use the array form delete in the destructor:



    CyclicBuffer::~CyclicBuffer()
    {
    delete buffer;
    }




    Style points



    Prefer initializers to assignment



    A constructor should initialize all the members of the class:



    CyclicBuffer::CyclicBuffer(std::size_t buffSize)
    : buffer(new char[bufferSize]),
    bufferSize(buffSize),
    head(0),
    tail(0)
    {
    }


    A good compiler will warn you if you have uninitialized members (e.g. g++ -Wall -Wextra).



    Note that I've also changed the argument to be a size_t, as a negative size is meaningless. The int members should all be size_t, too.



    Avoid numeric character constants



    What's special about the number 45? If you care about its character value, (and if you're using an ASCII-like system), it's clearer to write '-' instead.



    Drop the commented-out code



    I don't want to see using std::namespace;, ever. Not even in a comment.






    share|improve this answer














    Improve the wrap-around logic



    There's obvious inefficiency in:



    head %= bufferSize;


    % uses division, but because we're incrementing, we know that head / bufferSize is at most 1. Instead, we can:



    if (++head >= bufferSize)
    head -= bufferSize;


    On architectures such as ARM, there's no branch here, as any decent compiler will just use a condition flag on the subtraction.





    Consider checking for overrun and underrun



    At the moment, this buffer has no checking for the read and write positions crossing each other. Perhaps that's what you need, but it's quite unusual to have an unchecked circular buffer, and if you were holding (e.g.) audio data, you can imagine how it would sound, given the output you show.





    Match new and delete



    Since you create buffer using new, you must use the array form delete in the destructor:



    CyclicBuffer::~CyclicBuffer()
    {
    delete buffer;
    }




    Style points



    Prefer initializers to assignment



    A constructor should initialize all the members of the class:



    CyclicBuffer::CyclicBuffer(std::size_t buffSize)
    : buffer(new char[bufferSize]),
    bufferSize(buffSize),
    head(0),
    tail(0)
    {
    }


    A good compiler will warn you if you have uninitialized members (e.g. g++ -Wall -Wextra).



    Note that I've also changed the argument to be a size_t, as a negative size is meaningless. The int members should all be size_t, too.



    Avoid numeric character constants



    What's special about the number 45? If you care about its character value, (and if you're using an ASCII-like system), it's clearer to write '-' instead.



    Drop the commented-out code



    I don't want to see using std::namespace;, ever. Not even in a comment.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 12 at 14:11

























    answered May 25 '17 at 9:55









    Toby Speight

    23.2k538110




    23.2k538110












    • Regarding the suggested fix about % division, since it is always incrementing, we can put if (++head >= bufferSize) head = 0; right? And it should be more efficient as we are avoiding the subtraction. Am I missing something here?
      – Anubis
      Jun 28 at 10:55












    • No, you're missing nothing - assigning zero is less work than subtraction, and would be a further improvement.
      – Toby Speight
      Jul 4 at 7:20






    • 2




      @TobySpeight : In fact, // is the best prefix for using namespace std;
      – Calak
      Nov 12 at 14:57


















    • Regarding the suggested fix about % division, since it is always incrementing, we can put if (++head >= bufferSize) head = 0; right? And it should be more efficient as we are avoiding the subtraction. Am I missing something here?
      – Anubis
      Jun 28 at 10:55












    • No, you're missing nothing - assigning zero is less work than subtraction, and would be a further improvement.
      – Toby Speight
      Jul 4 at 7:20






    • 2




      @TobySpeight : In fact, // is the best prefix for using namespace std;
      – Calak
      Nov 12 at 14:57
















    Regarding the suggested fix about % division, since it is always incrementing, we can put if (++head >= bufferSize) head = 0; right? And it should be more efficient as we are avoiding the subtraction. Am I missing something here?
    – Anubis
    Jun 28 at 10:55






    Regarding the suggested fix about % division, since it is always incrementing, we can put if (++head >= bufferSize) head = 0; right? And it should be more efficient as we are avoiding the subtraction. Am I missing something here?
    – Anubis
    Jun 28 at 10:55














    No, you're missing nothing - assigning zero is less work than subtraction, and would be a further improvement.
    – Toby Speight
    Jul 4 at 7:20




    No, you're missing nothing - assigning zero is less work than subtraction, and would be a further improvement.
    – Toby Speight
    Jul 4 at 7:20




    2




    2




    @TobySpeight : In fact, // is the best prefix for using namespace std;
    – Calak
    Nov 12 at 14:57




    @TobySpeight : In fact, // is the best prefix for using namespace std;
    – Calak
    Nov 12 at 14:57












    up vote
    0
    down vote













    Constructor initialization - 0 out the array



    buffer(new T[size]{}) will set all the values to 0 instead of random garbage



    template<class T>
    CyclicBuffer<T>::CyclicBuffer(std::size_t size): head(0), tail(0), buffer(new T[size]{}), size(size) {

    }


    Adding and Getting can use equality comparison



    Comparing equality rather than subtracting/greater or equals makes it more readable





    template<class T>
    void CyclicBuffer<T>::add(T val) {
    if (head == size)
    head = 0;

    buffer[head++] = val;
    }

    template<class T>
    T CyclicBuffer<T>::get() {
    if (tail == size)
    tail = 0;

    return buffer[tail++];
    }


    Use template to make your structure generic



    You will be able to insert any type:



    CyclicBuffer<char> charCyclicBuffer(5);
    CyclicBuffer<int> intCyclicBuffer(5);


    Use std::size_t for portability



    Besides portability - size, head, tail will never be negative



    template<class T>
    class CyclicBuffer{
    public:
    explicit CyclicBuffer(std::size_t size);

    ~CyclicBuffer();

    void add(T val);

    T get();

    inline std::size_t getSize() {
    return this->size;
    }

    private:
    T *buffer;
    std::size_t size;
    std::size_t head;
    std::size_t tail;
    };





    share|improve this answer








    New contributor




    Eugene Barnett is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






















      up vote
      0
      down vote













      Constructor initialization - 0 out the array



      buffer(new T[size]{}) will set all the values to 0 instead of random garbage



      template<class T>
      CyclicBuffer<T>::CyclicBuffer(std::size_t size): head(0), tail(0), buffer(new T[size]{}), size(size) {

      }


      Adding and Getting can use equality comparison



      Comparing equality rather than subtracting/greater or equals makes it more readable





      template<class T>
      void CyclicBuffer<T>::add(T val) {
      if (head == size)
      head = 0;

      buffer[head++] = val;
      }

      template<class T>
      T CyclicBuffer<T>::get() {
      if (tail == size)
      tail = 0;

      return buffer[tail++];
      }


      Use template to make your structure generic



      You will be able to insert any type:



      CyclicBuffer<char> charCyclicBuffer(5);
      CyclicBuffer<int> intCyclicBuffer(5);


      Use std::size_t for portability



      Besides portability - size, head, tail will never be negative



      template<class T>
      class CyclicBuffer{
      public:
      explicit CyclicBuffer(std::size_t size);

      ~CyclicBuffer();

      void add(T val);

      T get();

      inline std::size_t getSize() {
      return this->size;
      }

      private:
      T *buffer;
      std::size_t size;
      std::size_t head;
      std::size_t tail;
      };





      share|improve this answer








      New contributor




      Eugene Barnett is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




















        up vote
        0
        down vote










        up vote
        0
        down vote









        Constructor initialization - 0 out the array



        buffer(new T[size]{}) will set all the values to 0 instead of random garbage



        template<class T>
        CyclicBuffer<T>::CyclicBuffer(std::size_t size): head(0), tail(0), buffer(new T[size]{}), size(size) {

        }


        Adding and Getting can use equality comparison



        Comparing equality rather than subtracting/greater or equals makes it more readable





        template<class T>
        void CyclicBuffer<T>::add(T val) {
        if (head == size)
        head = 0;

        buffer[head++] = val;
        }

        template<class T>
        T CyclicBuffer<T>::get() {
        if (tail == size)
        tail = 0;

        return buffer[tail++];
        }


        Use template to make your structure generic



        You will be able to insert any type:



        CyclicBuffer<char> charCyclicBuffer(5);
        CyclicBuffer<int> intCyclicBuffer(5);


        Use std::size_t for portability



        Besides portability - size, head, tail will never be negative



        template<class T>
        class CyclicBuffer{
        public:
        explicit CyclicBuffer(std::size_t size);

        ~CyclicBuffer();

        void add(T val);

        T get();

        inline std::size_t getSize() {
        return this->size;
        }

        private:
        T *buffer;
        std::size_t size;
        std::size_t head;
        std::size_t tail;
        };





        share|improve this answer








        New contributor




        Eugene Barnett is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.









        Constructor initialization - 0 out the array



        buffer(new T[size]{}) will set all the values to 0 instead of random garbage



        template<class T>
        CyclicBuffer<T>::CyclicBuffer(std::size_t size): head(0), tail(0), buffer(new T[size]{}), size(size) {

        }


        Adding and Getting can use equality comparison



        Comparing equality rather than subtracting/greater or equals makes it more readable





        template<class T>
        void CyclicBuffer<T>::add(T val) {
        if (head == size)
        head = 0;

        buffer[head++] = val;
        }

        template<class T>
        T CyclicBuffer<T>::get() {
        if (tail == size)
        tail = 0;

        return buffer[tail++];
        }


        Use template to make your structure generic



        You will be able to insert any type:



        CyclicBuffer<char> charCyclicBuffer(5);
        CyclicBuffer<int> intCyclicBuffer(5);


        Use std::size_t for portability



        Besides portability - size, head, tail will never be negative



        template<class T>
        class CyclicBuffer{
        public:
        explicit CyclicBuffer(std::size_t size);

        ~CyclicBuffer();

        void add(T val);

        T get();

        inline std::size_t getSize() {
        return this->size;
        }

        private:
        T *buffer;
        std::size_t size;
        std::size_t head;
        std::size_t tail;
        };






        share|improve this answer








        New contributor




        Eugene Barnett is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.









        share|improve this answer



        share|improve this answer






        New contributor




        Eugene Barnett is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.









        answered 1 hour ago









        Eugene Barnett

        1




        1




        New contributor




        Eugene Barnett is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.





        New contributor





        Eugene Barnett is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.






        Eugene Barnett is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f164130%2felegant-circular-buffer%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Create new schema in PostgreSQL using DBeaver

            Deepest pit of an array with Javascript: test on Codility

            Costa Masnaga