I'm new to C++ and am doing the C++ 4th Edition Stroustrup book. I expanded on one of the examples, and have a few questions to ask (embedded within the code: ////QUESTION 1-9).
Please provide any critiques, I'd like to bang in safe practice as early as possible. The Vector.h file simply declares these functions, and two private members, elem (list of elements, int*) and sz (the size, int).
Vector::Vector(std::initializer_list<int> list) //called via list init: ie, Vector v = {1, 2, 3, 4};
:elem{ new int[list.size()] }, sz{ list.size() }
{
copy(list.begin(), list.end(), elem); //copy list from start to end to elem
}
Vector::Vector(int s) //Constructor w/ size
{
if (s < 0) throw length_error{"Vector::Vector"};
elem = new int[s];
for (int i = 0; i < s; i++)
elem[i] = 0; //init elems to 0
sz = s;
}
Vector::Vector(const Vector& a) //copy constructor - rule of 3 (if destructor then copy constructor & copy assignment op)
:elem{ new int[sz] },
sz{ a.sz } ////QUESTION 1
{
for (int i = 0; i < sz; i++)
elem[i] = a.elem[i];
}
Vector::Vector() //empty constructor - functionally useless
{
sz = 0;
}
Vector::~Vector() { //DESTRUCTOR
cout << "DESTRUCTOR TRIGGERED! END OF DAYS COMING\n";
delete[] elem;
}
int& Vector::operator[](int i) const { ////QUESTION 2
if (i<0 || i>=size()) throw out_of_range{ "Vector::operator[]" };
return elem[i];
}
Vector& Vector::operator=(const Vector& a) { //copy assignment op
int* p = new int[a.sz];
for (int i = 0; i < sz; i++) ////QUESTION 3
p[i] = a.elem[i];
delete[] elem;
this->elem = p;
this->sz = a.sz;
return *this;
}
const bool Vector::operator==(Vector& right) const { ////QUESTION 4
if (size() != right.size())
return false;
else {
for (int i = 0; i < size(); i++){ //left and right have same size, doesn't matter which
if (elem[i] != right[i])
return false;
}
}
return true;
} ////QUESTION 5
//MEMSAFE (or so I like to think?)
Vector& Vector::operator+=(const Vector& a) {
int* p = new int[sz + a.sz];
for (int i = 0; i < sz; i++)
p[i] = elem[i];
for (int i = sz, ctr = 0; i < sz + a.sz; i++, ctr++)
p[i] = a.elem[ctr];
delete[] elem;
this->elem = p;
this->sz += a.sz;
return *this;
}
const Vector& Vector::operator++() {
this->pushBack(0);
return *this;
}
//MEMSAFE
////QUESTION 6
const Vector& Vector::operator--() {
//delete elem[sz - 1]; //delete (elem+sz); //this hates me.
this->sz -= 1;
return *this;
}
const Vector Vector::operator+(const Vector& a) { ////QUESTION 7
if (this->sz != a.sz)
return NULL;
Vector v = sz; //init's Vector with all 0's ( O(2n) with this init, and the for loop below..)
for (int i = 0; i < this->sz; i++)
v.elem[i] = elem[i] + a.elem[i];
return v;
}
const Vector& Vector::operator+(int x) {
this->pushBack(x); //recycling working code
return *this;
}
//Returns a Vector with the calling Vector's remaining elem's (ie, all except last) - doesn't affect calling Vector in any way
Vector Vector::softRest() const {
Vector v = *this;
int* p = new int[v.sz - 1];
for (int i = 0; i < sz - 1; i++)
p[i] = v[i + 1];
delete[] v.elem;
v.elem = p;
v.sz -= 1;
return v;
} //seems wildly inefficient, suggestions?
//Sets the calling Vector to be all elem's except last.
const Vector& Vector::hardRest() {
int* p = new int[sz - 1];
for (int i = 0; i < sz - 1; i++)
p[i] = elem[i + 1];
delete[] elem;
this->elem = p;
this->sz -= 1;
return *this;
}
const Vector& Vector::pushBack(int x) {
int* temp = new int[sz + 1];
for (int i = 0; i < sz; i++)
temp[i] = elem[i];
temp[sz] = x; //temp is new int[sz+1]; so temp[sz] = last elem
delete[] elem; ////QUESTION 8
this->elem = temp;
this->sz += 1;
return *this;
}
//MEMSAFE
void Vector::addToEnd(std::initializer_list<int> list) {
Vector v(list);
this->operator+=(v);
}
int Vector::size() const {
return this->sz; ////QUESTION 9
}
Questions (for ease of reading, they still have their placeholders in the code to let you know what I'm referring to):
How would it differ if I set
elem&szin the body of the constructor? As of now, they are being declared after the method declaration, but before the start of the actual function (in the Copy Constructor).removed
I use the
szvariable, as an upperbound for a loop. What is safest? Should I usesz,this->sz,size()orthis->size()?size()is a function within the code which returnsthis->sz;Am I overusing
const? Since there are no assignment operators within the function, it doesn't perform any changes to its class members - so is the lastconstuseless?My
operator==(Vector&)function is pretty ugly. Any suggestions for a nicer/more efficient solution?In my
operator--()function (which is meant to remove the last element in the vector), I simply reduce theszvariable for the calling vector by 1. I'm not actually deleting anything. Is this bad practice? What is a better solution? Is there a way todeletea single entry in an array?I understand that
a(const Vector& aargument to theoperator+(..)function) is aconst, but the function doesn't change the argument whatsoever. If the function remains as is, could I remove theconstdeclaration which prepends the argument?In my
pushBack(int)function, anintarray (calledtemp) is created usingnew- which means it must be deleted. However, using_CrtDumpMemoryLeaks();, I get no objection from the compiler. Is this because it automatically self-deconstructs because it's anintarray?Why shouldn't my
size()returnszinstead ofthis->sz. Am I correct in understanding this is primarily for multithreaded reasons?
EDIT:
Class declaration (Vector.h) -
#include <initializer_list>
#include <iostream>
#include <stdexcept>
using namespace std;
class Vector {
public:
//Constructors
Vector(std::initializer_list<int>); //constructor with {x, y, z} init (ie Vector v({1, 2, 3}); )
Vector(int); //declare size, and initialize all elements to 0
Vector(); //empty constructor
Vector(const Vector& a); //COPY CONSTRUCTOR - rule of 3
~Vector(); //DESTRUCTOR - rule of 3
//Overloaded operators
int& operator[](int) const; //function type: int& because returns a[i] (or &a[i])
const Vector& operator++();
const Vector& operator--();
const bool operator==(Vector&) const;
Vector& operator=(const Vector&); //COPY ASSIGNMENT - rule of 3
Vector& operator+=(const Vector&); //a Vector, += a vector (since its IN the vector class)
const Vector operator+(const Vector&); //adds values of two equal sized vectors
const Vector& operator+(int); //deals with adding a single int (essentially .pushBack(int))
//Input functions
const Vector& pushBack(int); //add single element to end
void addToEnd(std::initializer_list<int>); //add list to end
Vector softRest() const;
const Vector& hardRest();
//Output functions
int size() const;
void arr_print() const;
private:
int sz;
int* elem;
};
operator[]? I can't find them in 13.6.1 (pp.375) \$\endgroup\$constwas my own useless addition. \$\endgroup\$