Created
January 2, 2019 13:59
-
-
Save Holt59/0a9bc4bf327598daf3b841ee7a17bbad to your computer and use it in GitHub Desktop.
List implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Extra comments: | |
// - Check the copy-and-swap idiom, i.e., implement a swap method for your List and then use it | |
// for the copy and move operator: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-and-swap | |
// - Do not provide constructor or operator that takes non-const reference, see the rule or 0/3/5: | |
// https://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29 | |
// - There are a lot of utility functions in the C++ standard that could help you, in particular, | |
// check copy and copy_n: https://en.cppreference.com/w/cpp/algorithm/copy or equal_range | |
// https://en.cppreference.com/w/cpp/algorithm/equal_range | |
#include <stdexcept> | |
struct outOfScope: public std::exception { | |
const char* what () const noexcept; | |
}; | |
struct pointerInitialization: public std::exception { | |
const char* what () const noexcept; | |
}; | |
template<class T> | |
class List { | |
public: | |
// Do not use NULL, use nullptr | |
T *p = nullptr; | |
int s; | |
public: | |
// Use member-list initializer instead of initialization in body. | |
List() : p{nullptr}, s{0} {} | |
// User member-list initialization for s. | |
List(int i) : s{i} { | |
// p cannot be since it's a constructor. | |
try { | |
p = new T [s]; | |
} | |
catch (std::bad_alloc const&) { | |
throw pointerInitialization(); | |
} | |
} | |
// Copy constructor - Use delegating constructor: | |
List(const List<T>& l) : List{l.s} { | |
for(int i=0; i<s; i++) { | |
p[i] = l.p[i]; | |
} | |
} | |
// Move constructor - | |
List(List<T> &&l) : s{l.s}, p{l.p} { | |
// Reset l for correct destruction. | |
l.s = 0; | |
l.p = nullptr; | |
} | |
// Do not provide List(List<T> &), this is useless since you | |
// have List(List<T> const&). | |
bool operator==(const List<T>& l) { | |
// Compare size first: | |
if (s != l.s) { | |
return false; | |
} | |
bool check = true; | |
for(int i=0; i<l.s; i++) { | |
if(p[i] != l.p[i]) { | |
check = false; | |
break; | |
} | |
} | |
return check; | |
} | |
bool operator!=(const List<T>& l) { | |
// Compare size first: | |
if (s != l.s) { | |
return false; | |
} | |
bool check = false; | |
for(int i=0; i<l.s; i++) { | |
if(p[i] != l.p[i]) { | |
check = true; | |
break; // Early break | |
} | |
} | |
return check; | |
} | |
// operator= should return a reference to this | |
List<T>& operator=(const List<T>& other) { | |
// Check that you are not assigning to yourself: | |
if (this != &other) { | |
if(p) { | |
// No need to set p to nullptr since you are reassigning | |
delete [] p; | |
} | |
s = other.size(); | |
try { | |
p = new T [s]; | |
} | |
catch (std::bad_alloc const&) { | |
throw pointerInitialization(); | |
} | |
for(int i=0; i<s; i++) { | |
p[i] = other.p[i]; | |
} | |
} | |
return *this; | |
} | |
// Do not provide operator=(List<T>&) | |
// Move assignment: | |
List<T>& operator=(List<T>&& other) { | |
// Just swap. | |
std::swap(s, other.s); | |
std::swap(p, other.p); | |
return *this; | |
} | |
~List() { | |
delete [] p; | |
// No need to assign p to nullptr. | |
} | |
// Set values is useless since you can do: | |
// l = List<T>(i) | |
// with no additional cost thanks to the move. | |
T& operator[](int i) { | |
if(i < s && i >= 0) { | |
return p[i]; | |
} | |
throw outOfScope(); | |
} | |
// You want to provide a const-overload of operator[]: | |
const T& operator[](int i) const { | |
if (i < s && i >= 0) { | |
return p[i]; | |
} | |
throw outOfScope(); | |
} | |
// size() should be const-qualified: | |
int size() const { return s; } | |
void addAtEnd(T newEntry) { | |
s = s+1; | |
T* newP = new T[s]; | |
newP[s-1] = newEntry; | |
for(int i=0; i<s-1; i++) { | |
newP[i] = p[i]; | |
} | |
delete [] p; | |
// Do not reallocate, simply reassign p: | |
p = newP; | |
} | |
int find(T value) { | |
int count = 0; | |
for(int i=0; i < s; i++) { | |
if(p[i]==value) { | |
return i; | |
} | |
} | |
// You usually returns -1 if you did not find: | |
return -1; | |
} | |
List<int> findAll(T value) const { | |
List<int> locList; | |
for(int i=0; i<s; i++) | |
{ | |
if(p[i]==value) | |
{ | |
locList.addAtEnd(i); | |
} | |
} | |
return locList; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have few queries as I am new to c++ and am writing codes for my CFD solver (computational fluid dynamics solver) which basically reads mesh generated by any standard CAD software (like ansys, catia, solidworks etc) and solves a set of partial differential equations on it using finite volume method iteratively which involves the use a matrix solver that solves Ax = b. For me computational cost is very important i.e. I would be working with billions of grid points in a domain at a time which might take weeks to get the solutions. In that regard, I wanted to ask you what is the computationally most effective way to use operator overloading. For example: I cannot pass by address the local variables of a operator overload function (e.g. operator+, which adds to vectors and return a vector, similarly dot product, cross product etc).
2nd most important thing is: I have to avoid memory leak at any cost because it involves huge computations for more than weeks, so even one small leak can cause my process to shut down. To avoid getting into any trouble, I am always trying to equate a pointer to NULL after deleting it. Moreover, if I don't use try-catch function and rather call just throw myExceptions() (say), it gives the message and also stops the programme which is good because it doesn't proceed with the wrong data. If I use try-catch, it throws exceptions but programme continues from the next line, which is very dangerous in my case. Is it the correct way of doing it to achieve what I wanted? If not, kindly correct me. Thanks for listening!