Question
CSE 232, Lab Exercise 12 We are going to work on making our own container class with dynamic memory. We are going to build our
CSE 232, Lab Exercise 12
We are going to work on making our own container class with dynamic memory. We are going to build our own version of a vector that is templated, as it should be
Namespaces
We have talked a lot about namespaces but really haven't used them ourselves. It turns out we can easily define our own namespaces to separate code that we have defined from code in the standard library. We are going to do that here, define a namespace called student in which we will place a class vector. Though vector has the same name as in the STL, because we store it in our own namespace we can change just a single line of code to use our namespace student version of vector or the stl version.
Making a namespace
Turns out it is rather easy to make a namespace. You can enclose all the code you want to define in a namespace in brackets lead by a declaration of the namespace. For example: namespace student {
templateclass vector{ ...
} Everything in curly brackets is now part of the student namespace. You can add things to the student namespace by simply adding other namespace student elements in the code. To use your new namespace (with your new vector class), you would use:
student::vector
instead of
std::vector
Multiple mains
We are going to do this in stages. Each stage will have a main.cpp associated with it (main1.cpp, main2.cpp, etc.) so that you can test as far as you get with the code.
Task 1
1. Create a vector.h file a. because we are creating a templated class, everything goes in the hearder. We won't
have a vector.cpp.
In vector.h create a namespace student as described above
In namespace student, create a template vector class with the following private
features:
a pointer data_ of template type which point to dynamically allocated memory
a size_t capacity_, default 10, which is the capacity of the vector.
Remember, capacity is how many elements it could hold before having to grow.
a size_t size_, default 0, the number of elements actually in the vector.
4 methods
a 1-arg constructor with argument capacity. It will do the following:
set capacity_ to the argument (or 10 if no argument using the default)
set size_ to 0
set data_ to point to a dynamically allocated memory element of template type,
and the size of that array will be the capacity_ value (default 10)
a destructor
remember, destructor is named with class type preceeded by a ~
it should delete the memory pointed to by data_
a method size_t capacity()
a. returns the capacity_ value 4. a method size_t size()
a. returns the size_ value Run this code against the main labeled main1.cpp.
Show your TA Task 2
Create two important methods
voidpush_back(templatetypeval); templatetype&operator[](size_tval);
Fix vector.h to have these new declarations and create the method in the namespace student of vector.h
push_back
Remember the special functionality of push_back.
A vector is never full (well, unless your machine runs out of memory). The capacity_ of vector indicates how many elements it can hold , whereas size_ indicates how many it acutally presently holds, before the memory pointed to by data_ needs to grow. If a push_back exceeds this capacity, you must do the following:
1. Create a new memory allocation that is twice the size of what data_ points to presently a. call the new pointer new_data
copy all the elements in data_ into new_data
swap data_ and new_data (now data_ points to the larger memory)
delete new_data (which now points to the old memory)
update capacity_
push_back the new element onto vector
operator[]
This is the operator that allows us to work with individual elements in our vector. operator[] receives a single size_t argument which is the index in the original call and returns a reference to the element. You can do one of two things:
if the index requested is within the vector, return a reference to the element at that location
if it is not, throw a range_error (requires #include
Run your code with main2.cpp to see if it works. Show your TA when you have finished.
Task 3
If you got this far, here is some more fun stuff. First the easy ones. Write the following two functions:
a front() method that returns a reference to the front element of the vector
a back() method that returns a reference to the back element of the vector
o what should these do if the vector is empty?
Then the harder ones. If you do dynamic memory, you should make your own copy constructor and operator=. So write the next three functions:
vector(vector&v); vector&operator=(vector&v); ~vector()
The copy constructor should:
copy both capacity_ and size_ from v to the newly created instance
in the new created instance
o allocate the new required memory o copy the elements from the argument vector to the newly created instance.
The operator= should basically do the same thing
think of using the copy and swap idiom from class
Then ~vector(), the destructor to manage memory when the created element goes out of scope or is otherwise destroyed
Run your code with main3.cpp to see if it works Show it to your TA
Task 4
Finally, if you are still here, let's make
a clear() method which removes all the data o resets both capacity_ and size_, to 0 o deletes the existing array memory (if there is any)
a pop_back method. FYI one would only do the following on a system with limited memory, but it is still good practice:
o it returns a template type, the last element of the vector o removes the last element of the vector. The vector size_ is now one less o if after the removal the vector reaches 12 capacity (the size_ is half of the
capacity_), do what we did with push_back but in reverse. make a new_data pointer of half capacity copy the data_ to the new_data clean up as previously
Run your code with main4.cpp to see if it works
---------- main1.cpp ----------
#include
using std::cout; using std::endl; #include "vector.h" using student::vector; int main () { vectorv; cout << "Size : " << v.size() << endl; cout << "Capacity : " << v.capacity() << endl; }
---------- main2.cpp ----------
#includeusing std::cout; using std::endl; #include "vector.h" using student::vector; int main () { vector v; cout << "Size : " << v.size() << endl; cout << "Capacity : " << v.capacity() << endl; for(auto i = 0u; i < 12; i++) { v.push_back(i); } cout << "Size : " << v.size() << endl; cout << "Capacity : " << v.capacity() << endl; for(auto i = 0u; i < v.size(); i++) { cout << v[i] << ", "; } cout << endl; try { cout << v[100] << endl; } catch (const std::exception& e) { cout << "A standard exception was caught, with message '" << e.what() << "'" << endl; } }
----------main3.cpp----------
#includeusing std::cout; using std::endl; using std::ostream; #include using std::ostringstream; #include "vector.h" using student::vector; void print_vector(vector & v, ostream& out) { ostringstream oss; for(auto i = 0u; i < v.size(); i++) { oss << v[i] << ", "; } out << oss.str().substr(0, oss.str().length() - 2) << endl; } int main () { vector v; cout << "Size : " << v.size() << endl; cout << "Capacity : " << v.capacity() << endl; for(auto i = 0u; i < 12; i++) { v.push_back(i); } cout << "Size : " << v.size() << endl; cout << "Capacity : " << v.capacity() << endl; cout << "v : "; print_vector(v, cout); cout << "v.front(): " << v.front() << endl; cout << "v.back() : " << v.back() << endl; cout << endl; try { cout << v[100] << endl; } catch (const std::exception& e) { cout << "A standard exception was caught, with message '" << e.what() << "'" << endl; } try { vector v; cout << v.front() << endl; } catch (const std::exception& e) { cout << "A standard exception was caught, with message '" << e.what() << "'" << endl; } try { vector v; cout << v.back() << endl; } catch (const std::exception& e) { cout << "A standard exception was caught, with message '" << e.what() << "'" << endl; } cout << endl; vector v2(v); v2.push_back(100); v2[4] = 444; cout << "v : "; print_vector(v, cout); cout << "v2 : "; print_vector(v2, cout); cout << endl; vector v3; v3 = v2; v3.push_back(200); cout << "v2 : "; print_vector(v2, cout); cout << "v3 : "; print_vector(v3, cout); cout << endl; }
---------- main4.cpp ----------
#includeusing std::cout; using std::endl; using std::ostream; #include using std::ostringstream; #include "vector.h" using student::vector; void print_vector(vector & v, ostream& out) { ostringstream oss; for(auto i = 0u; i < v.size(); i++) { oss << v[i] << ", "; } out << oss.str().substr(0, oss.str().length() - 2) << endl; } int main () { vector v; cout << "Size : " << v.size() << endl; cout << "Capacity : " << v.capacity() << endl; for(auto i = 0u; i < 12; i++) { v.push_back(i); } cout << "Size : " << v.size() << endl; cout << "Capacity : " << v.capacity() << endl; cout << "v : "; print_vector(v, cout); cout << "v.front(): " << v.front() << endl; cout << "v.back() : " << v.back() << endl; cout << endl; try { cout << v[100] << endl; } catch (const std::exception& e) { cout << "A standard exception was caught, with message '" << e.what() << "'" << endl; } try { vector v; cout << v.front() << endl; } catch (const std::exception& e) { cout << "A standard exception was caught, with message '" << e.what() << "'" << endl; } try { vector v; cout << v.back() << endl; } catch (const std::exception& e) { cout << "A standard exception was caught, with message '" << e.what() << "'" << endl; } cout << endl; vector v2(v); v2.push_back(100); v2[4] = 444; cout << "v : "; print_vector(v, cout); cout << "v2 : "; print_vector(v2, cout); cout << endl; vector v3; v3 = v2; v3.push_back(200); cout << "v2 : "; print_vector(v2, cout); cout << "v3 : "; print_vector(v3, cout); cout << endl; for (auto i = 0u; i < 10; i++) { v.pop_back(); } cout << "v.front() : " << v.front() << endl; cout << "v.back() : " << v.back() << endl; cout << "v.size() : " << v.size() << endl; cout << "v.capacity() : " << v.capacity() << endl; v.clear(); cout << endl; cout << "v.size() : " << v.size() << endl; cout << "v.capacity() : " << v.capacity() << endl; }
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started