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
&sz
in 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
sz
variable, 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 lastconst
useless?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 thesz
variable 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 todelete
a single entry in an array?I understand that
a
(const Vector& a
argument to theoperator+(..)
function) is aconst
, but the function doesn't change the argument whatsoever. If the function remains as is, could I remove theconst
declaration which prepends the argument?In my
pushBack(int)
function, anint
array (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 anint
array?Why shouldn't my
size()
returnsz
instead 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\$const
was my own useless addition. \$\endgroup\$