Learning how to use arrays in C++ is an extremely important skill to have as a programmer. Generally speaking, arrays are used to store data with identical types as a group. The simplest and most commonly used array is a vector, or 1D array. Creating, deallocating, and keeping track of array lengths can complicate programming. The C++ standard library has a very good implementation of a vector object, but is somewhat bloated for applications with tight memory requirements. std::vector
is also a template, which aren’t kosher in embedded and critical applications. Therefore, here is a simplified vector class for creating and managing vectors that I created.
Full source code for my vector class can be found on my GitHub repo.
My vector class has the following capabilities:
I will create a float
vector class, but the code could be easily modifed by replacing float
with double
, uint32_t
, etc.
The vector class is declared in it’s header file. This defines the constructor, deconstructor, methods, and access specifiers for each method and variable.
class Vectorf {
public:
Vectorf(size_t vecLen = 3);
~Vectorf();
void Fill(float val);
void Print();
size_t GetLen();
float Get(size_t index);
float GetNorm();
protected:
private:
size_t n; // Vector length
float *vec; // Vector's dynamic array
};
The constructor is called when we create a vector object. The input when creating a vector object will be it’s length, or the number of elements. The constructor then allocates the vector’s array in heap memory with the new
keyword. We have to use dynamic arrays since the array size is unknown until runtime. I added some error checks, too.
Vectorf::Vectorf(size_t vecLen) {
// Check if len is zero
if (vecLen == 0) {
throw std::invalid_argument("Vector length must be greater than zero");
}
this->n = vecLen; // vector length
// check for bad allocation
try {
this->vec = new float[this->n]; // Allocate array on the heap
}
catch (const std::bad_alloc &ba) {
std::cerr << "Bad vectorf array allocation: " << ba.what() << std::endl;
}
// Set initial values to zero
this->Fill(0.0f);
}
The following method returns the vector length, or the number of elements in the vector’s array. This could be used in external code when the length of a vector is unknown.
size_t Vectorf::GetLen() {
return this->n;
}
The Get()
method returns the vector’s value at the specified index. It also ensures the specified index is less than the vector’s length.
float Vectorf::Get(size_t index) {
// check the specified index
if (index > this->n) {
throw std::invalid_argument("Vector index exceeded length.");
}
return this->vec[index];
}
The fill()
method fills the entire array with a specified value. This method is also used in the constructor to initialize the vector with all zeros.
void Vectorf::Fill(float val) {
size_t ii;
for (ii = 0; ii < this->n; ii++) {
this->vec[ii] = val;
}
}
The GetNorm()
method computes the magnitude, or norm, of the vector. The mangitude is the square root of the sum of of the vector elements, squared.
$$ norm = \sqrt{x_0^2 + x_1^2 + x_2^2 + …} $$
float Vectorf::GetNorm() {
size_t ii;
float sum = 0.0f;
// Sum of the squares
for (ii = 0; ii < this->n; ii++)
sum += this->vec[ii] * this->vec[ii];
// return the square root
return sqrtf(sum);
}
The Print()
method prints the entire vector to the console. This could be useful for debugging purposes.
void Vectorf::Print() {
size_t ii;
std::cout << "[ "; // Left bracket
for (ii = 0; ii < this->n; ii++)
std::cout << this->vec[ii] << " "; // space between elements
std::cout << "]" << std::endl; // right bracket
}
The deconstructor deallocates the vector’s array after it goes out of scope. This is important so that the computer can use the array’s memory locations after the vector is out of scope.
Vectorf::~Vectorf() {
delete[] this->vec; // deallocate from the heap
}
The source code plus an example can be found at this GitHub repo. I hope this was useful and gave you some inspiration for your C++ projects!