Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

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 {

 template class 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) with an appropriate message. Look at the last lab.

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 () { vector v; cout << "Size : " << v.size() << endl; cout << "Capacity : " << v.capacity() << endl; } 

---------- main2.cpp ----------

#include  using 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----------

#include  using 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 ----------

#include  using 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

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image_2

Step: 3

blur-text-image_3

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Professional Microsoft SQL Server 2014 Integration Services

Authors: Brian Knight, Devin Knight

1st Edition

1118850904, 9781118850909

More Books

Students also viewed these Databases questions

Question

What is the Definition for Third Normal Form?

Answered: 1 week ago

Question

Provide two examples of a One-To-Many relationship.

Answered: 1 week ago