I created a class that created an array of ints and stored them as a vector would. I had it all working, but then I had to turn it into a template so that I could store more than just ints. I am getting the following errors and am not sure how to address them:
subscript is not of integral type (myvector.h line 70)
which is the line that says (vectorArray[vectorSize] = n;)
'initializing': conversion from 'double' to 'unsigned int', possible loss of data (myvector.h line 88)
Which is the line that says (T *tempArray = new T[newCapacity];)
subscript is not of integral type porj08 (myvector.h line 98)
Which is the line that says (tempArray[i] = vectorArray[i];)
'initializing': conversion from 'double' to 'unsigned int', possible loss of data (myvector.h line 102)
Which is the line that says (vectorArray = new T[newCapacity];)
subscript is not of integral type porj08 (myvector.h line 113)
Which is the line that says (vectorArray[vectorSize] = n;)
It obviously has something to do with vectorArray but I can not figure out for the life of me what I did wrong.
MyVector.h
#pragma once
#include <iostream>
#include "stdafx.h"
using namespace std;
template <class T>
class MyVector
{
private:
T vectorSize;
T vectorCapacity;
T *vectorArray;
public:
MyVector() {
vectorArray = new T[10];
}
T size();
T capacity();
void clear();
void push_back(T n);
T at(T n);
friend ostream& operator<<(ostream& os, MyVector vt);
MyVector operator=(MyVector&);
};
/*
* TEMPLATE FUNCTIONS
*/
//Return array size
template<class T>
T MyVector<T>::size()
{
return vectorSize;
}
// Return array capacity
template<class T>
T MyVector<T>::capacity()
{
return vectorCapacity;
}
// clear array values
template<class T>
void MyVector<T>::clear()
{
for (int i = 0; i < sizeof(vectorArray); i++)
{
vectorArray[i] = '\0';
}
vectorSize = 0;
vectorCapacity = 2;
}
// Add number to array and double array size if needed
template<class T>
void MyVector<T>::push_back(T n)
{
int test = 100;
if (vectorCapacity > vectorSize)
{
vectorArray[vectorSize] = n;
vectorSize++;
}
else {
if (vectorCapacity == 0) {
vectorArray = new T[4];
vectorArray[0] = n;
vectorCapacity = 4;
vectorSize++;
}
else {
T newCapacity = vectorCapacity * 2;
// Dynamically allocate a new array of integers what is somewhat larger than the existing array.An algorithm that is often used is to double the size of the array.
T *tempArray = new T[newCapacity];
// Change capacity to be the capacity of the new array.
vectorCapacity = newCapacity;
// Copy all of the numbers from the first array into the second, in sequence.
for (T i = 0; i < MyVector::size(); i++)
{
tempArray[i] = vectorArray[i];
}
delete[] vectorArray;
vectorArray = new T[newCapacity];
for (int i = 0; i < MyVector::size(); i++)
{
vectorArray[i] = tempArray[i];
}
delete[] tempArray;
// Add the new element at the next open slot in the new array.
vectorArray[vectorSize] = n;
// Increment the size;
vectorSize++;
}
}
}
// Return Value and given point in array
template<class T>
T MyVector<T>::at(T n)
{
return vectorArray[n];
}
Main.cpp
#include "stdafx.h"
#include <string>
#include "MyVector.h"
const double FRACTION = 0.5;
int main()
{
cout << "\nCreating a vector of doubles named Sam\n";
MyVector<double> sam;
cout << "\nPush 12 values into the vector.";
for (int i = 0; i < 12; i++)
sam.push_back(i + FRACTION);
cout << "\nHere is sam: ";
cout << sam;
cout << "\n---------------\n";
cout << "\nCreating an empty vector named joe";
MyVector<double> joe;
// test assignment
joe = sam;
cout << "\nHere is joe after doing an assignment:\n ";
cout << joe;
cout << "\n---------------\n";
// test the copy constructor
MyVector<double> bill = sam;
cout << "\nHere is bill after creating it using the copy constructor:\n ";
cout << bill;
cout << "\n---------------\n";
cout << endl;
system("PAUSE");
return 0;
}
T vectorSize;
T vectorCapacity;
If T is float for example, these will be float, obviously. You don't want that. Type of these members should not be dependent on the type T of elements, make it std::size_t, for example:
std::size_t vectorSize;
std::size_t vectorCapacity;
Then, beware sizeof(pointer) (you used one in clear), use vectorSize or vectorCapacity for loop conditions instead. That should cover all.
Related
I have these code:
#include<iostream>
#include<iomanip>
using namespace std;
class Array {
private:
static const int size = 100;
int arr[size];
public:
Array();
void display();
Array& operator+(const Array& arr);
};
Array::Array()
{
for (int i = 0; i < size; i++)
{
arr[i] = rand() % 99 + 1;
}
}
void Array::display()
{
for (int i = 0; i < size; i++)
{
cout << setw(5) << arr[i];
if ((i + 1) % 10 == 0)
cout << endl;
}
}
Array & Array::operator+(const Array & arr)
{
Array temp;
for (int i = 0; i < size; i++)
{
temp.arr[i] = this->arr[i] + arr.arr[i];
}
return temp;
}
int main()
{
srand(time(NULL));
Array arr1, arr2;
cout << "arreglo 1:\n";
arr1.display();
cout << endl;
cout << "arreglo 2:\n";
arr2.display();
cout << endl;
//adding both arr HERE IS MY PROBLEM
Array arr3 = arr1 + arr2;
cout << "Suma de arreglo 1 y arreglo 2: " << endl;
arr3.display();
cout << endl;
return 0;
}
Somehow it can't manage to display Array arr3 = arr1 + arr2.
Array & Array::operator+(const Array & arr)
{
Array temp;
...
return temp;
}
This returns a reference to an object that goes out of scope and is destroyed after the function returns. As a general rule you should not return addresses of or references to local variables.
Remove the & so it returns a new Array instead:
Array Array::operator+(const Array & arr)
I want to write a program that can use a dynamic array.
A size is to be passed via the constructor and as soon as this size is reached, a new array is generated in which the previous values are copied into it.
For this, I overloaded the [] operator. The program seems to work at first glance.
But after I tried to implement an array with the size 100 and to save 20000 elements here, different numbers are output.
At the first run, more than 7000 numbers were displayed. After another run over 1800. However, never the desired 20000.
What could be the reason for this?
#include <iostream>
using namespace std;
template<class T>
class Container{
public:
T *dynamicArray;
private:
T *newArray;
int size;
public:
Container(int size){
this->size=size;
dynamicArray=new T[size];
}
T operator[] (unsigned long index){
if(index>size-1){
newArray=new T[size+(index-size)];
T i;
for(i=0; i<(size+(index-size)); i++){
newArray[i]=dynamicArray[i];
}
delete[] dynamicArray;
dynamicArray=newArray;
delete[] newArray;
}
return dynamicArray[index];
}
};
int main()
{
Container <int> dArray(100);
for(int i=1; i<20000; i++){
dArray.dynamicArray[i]=i;
cout << dArray.dynamicArray[i] << "\n";
}
return 0;
}
Thank you!
first , this code didn't call the overloaded [] operator function , its just using default operator [] of type T array , and it never allocate any memory , you can output at allocate memory position
dArray.dynamischesArray[i]=i;
cout << dArray.dynamischesArray[i] << "\n";
and there it some error logic in the overloaded [] operator function
T operator[] (unsigned long index){
if(index>size-1){
neuesArray=new T[size+(index-size)];
T i;
for(i=0; i<(size+(index-size)); i++){
neuesArray[i]=dynamischesArray[i];
}
delete[] dynamischesArray;
dynamischesArray=neuesArray;
//delete[] neuesArray; cannot deleted ,course error
size = index + 1; //keep size sync real size
}
return dynamischesArray[index];
}
this is modified code can be run correct :
#include <iostream>
#include <string>
using namespace std;
template<class T>
class Container {
public:
T *dynamischesArray;
private:
T *neuesArray;
int size;
public:
Container(int size) {
this->size = size;
dynamischesArray = new T[size];
}
T& operator[] (unsigned long index) {
if (index > size - 1) {
cout << "allocate :" << index<<"\n";
neuesArray = new T[index+1];
unsigned long i;
for (i = 0; i < size; i++) {
neuesArray[i] = dynamischesArray[i];
}
delete[] dynamischesArray;
dynamischesArray = neuesArray;
//delete[] neuesArray;
size = index+1;
}
T&ret = dynamischesArray[index];
//return dynamischesArray[index];
return ret;
}
};
int main()
{
Container <int> dArray(100);
for (int i = 1; i < 20000; i++) {
dArray[i] = i;
cout <<"i="<<i<<" "<< dArray[i] << "\n";
//dArray.dynamischesArray[i] = i;
//cout << dArray.dynamischesArray[i] << "\n";
}
return 0;
}
this is result
I am trying to use the dynamic memory method instead of the vector method to add elements. Initially, the maximum size of the dynamic memory is set to 5. However, as soon as I try to increase more than the capacity of the current the dynamic memory, the elements of the 0th or 1st index loss their references.
The program works fine if I do not specify the size of the dynamic memory,
like: dynamic_memory = new int;. I am wondering why they lose their references
with the resize of the dynamic memory to more than the initial capacity.
PS: I am using Code::Block 16.01
Here is my program.
#include <iostream>
#include <cstdlib>
using namespace std;
class DynamicVector
{
public:
DynamicVector();
virtual ~DynamicVector();
void insertElement(int input);
int showCapacity();
int showSize();
void doubleSize(int * dynamic_memory);
friend ostream& operator << (ostream& outs, const DynamicVector obj);
private:
int * dynamic_memory;
int max_count; // this is similar to the capacity of the vector
int current_count; // this is similar to size of a vector
};
DynamicVector::DynamicVector()
{
max_count = 5;
dynamic_memory = new int[max_count];
current_count = 0;
}
DynamicVector::~DynamicVector()
{
delete [] dynamic_memory;
}
int DynamicVector::showCapacity(){
return max_count;
}
void DynamicVector::insertElement(int input)
{
if (current_count >= max_count)
doubleSize(dynamic_memory);
dynamic_memory[current_count] = input;
current_count++;
}
void DynamicVector::doubleSize(int * dynamic_memory){
int * tmp = new int[max_count];
for (int i = 0; i < max_count; i++)
tmp[i] = dynamic_memory[i];
delete [] dynamic_memory;
max_count = max_count * 2;
dynamic_memory = new int[max_count];
for (int i = 0; i < max_count; i++)
dynamic_memory[i] = tmp[i];
delete [] tmp;
}
int DynamicVector::showSize(){
return current_count;
}
ostream& operator <<(ostream& outs, const DynamicVector obj)
{
for (int i = 0; i < obj.current_count; i++)
outs << obj.dynamic_memory[i] << endl;
return outs;
}
int main()
{
DynamicVector v;
int numberOfIntendedElement = 11;
cout << "Previously, the capacity of vector was: " << v.showCapacity() << endl;
for (int i = 0; i < numberOfIntendedElement; i++)
v.insertElement(i);
cout << "The capacity of the new vector is: " << v.showCapacity() << endl;
cout << "The size of the new vector is: " << v.showSize() << endl;
cout << "The values in the dynamic vector are: \n" << v << endl;
return 0;
}
Result:
41107976
42075512
2
3
4
5
6
7
8
9
10
In
void doubleSize(int * dynamic_memory);
the dynamic_memory defined here shadows the member dynamic_memory; for comedic hi-jinks and undefined behaviour.
The local dynamic_memory is re-pointed at the new buffer, but the member dynamic_memory continues to point at the deleted original address after the function exits. This means that all subsequent inserts go into invalid memory, and Crom only knows what will happen after that.
Solution
Pass in nothing and use the member variable. Redefine the function as
void doubleSize();
Other problems are addressed in the comments and need to be fixed.
Thank you all for your valuable comments and suggestions, especially user4581301 for pointing a comedic hijinks and undefined behavior. After I redefined the function as void doubleSize(), it worked fine. Here is my final working code.
#include <iostream>
#include <cstdlib>
using namespace std;
class DynamicVector
{
public:
DynamicVector();
virtual ~DynamicVector();
void insertElement(int input);
int showCapacity();
int showSize();
void doubleSize();
friend ostream& operator << (ostream& outs, const DynamicVector obj);
private:
int * dynamic_memory;
int max_count; // this is similar to the capacity of the vector
int current_count; // this is similar to size of a vector
};
DynamicVector::DynamicVector()
{
max_count = 5;
dynamic_memory = new int[max_count];
current_count = 0;
}
DynamicVector::~DynamicVector()
{
delete [] dynamic_memory;
}
int DynamicVector::showCapacity(){
return max_count;
}
void DynamicVector::insertElement(int input)
{
if (current_count >= max_count)
doubleSize();
dynamic_memory[current_count] = input;
current_count++;
}
void DynamicVector::doubleSize(){
int * tmp = new int[max_count];
for (int i = 0; i < max_count; i++)
tmp[i] = dynamic_memory[i];
delete [] dynamic_memory;
max_count = max_count * 2;
dynamic_memory = new int[max_count];
for (int i = 0; i < max_count/2; i++)
dynamic_memory[i] = tmp[i];
delete [] tmp;
}
int DynamicVector::showSize(){
return current_count;
}
ostream& operator <<(ostream& outs, const DynamicVector obj)
{
for (int i = 0; i < obj.current_count; i++)
outs << obj.dynamic_memory[i] << endl;
return outs;
}
int main()
{
DynamicVector v;
int numberOfIntendedElement = 11;
cout << "Previously, the capacity of vector was: " << v.showCapacity() << endl;
for (int i = 0; i < numberOfIntendedElement; i++)
v.insertElement(i);
cout << "The capacity of the new vector is: " << v.showCapacity() << endl;
cout << "The size of the new vector is: " << v.showSize() << endl;
cout << "The values in the dynamic vector are: \n" << v << endl;
return 0;
}
Output
Previously, the capacity of vector was: 5
The capacity of the new vector is: 20
The size of the new vector is: 11
The values in the dynamic vector are:
0
1
2
3
4
5
6
7
8
9
10
I am fairly new to programming and our teacher had us create our own vector class. Everything works as needed, however once I hit the bottom and try to use the printV function, the size of the function is increased to a really large number instead of retaining the size of the vector. I will include all of the code below.
using namespace std;
class MyVector
{
private:
int vectorSize;
int maxCapacity;
int *myArray;
public:
//default constructor
//purpose: Initializes all variables
MyVector(void);
//Parameterized Constructor
//Purpose: creates a vector of capacity n
//parameters: int
MyVector(int);
//destructor
//Purpose: deletes and dynamically allocated storage
~MyVector(void);
// Overloaded assignment operator
// Purpose: to do assignment from one vector to another
// Parameters: a MyVector object
// Returns: A MyVector object
MyVector operator + (MyVector&);
// Copy constructor
// Purpose: Copy the data into this vector
// Parameters: a MyVector object
// Returns: none
MyVector(const MyVector&);
//size function
//purpose: gets the size of the vector
//returns: size
int size() const;
//capacity function
//purpose: gets the capacity of the vector
//returns: capacity
int capacity() const;
//clear function
//purpose: deletes all elements from the vector and resets its size to zero and capacity 2
//returns: nothing
void clear();
//push_back function
//purpose: adds an integer value at the end of the vector
//returns: nothing
void push_back(int n);
//at function
//purpose: returns the value of the element at position i in the vector
int at(int) const;
};
ostream& operator<<(ostream&, const MyVector&);
Here is the cpp file
#include "MyVector.h"
MyVector::MyVector(void)
{
maxCapacity = 2;
myArray = new int[maxCapacity];
vectorSize = 0;
}
MyVector::MyVector(int i)
{
maxCapacity = i;
myArray = new int[maxCapacity];
vectorSize = 0;
}
MyVector::~MyVector(void)
{
if (myArray != NULL);
{
delete [] myArray;
myArray = NULL;
}
}
MyVector MyVector::operator+(MyVector& rho)
{
if (this == &rho)
{
return *this;
}
delete [ ] this->myArray;
vectorSize = rho.vectorSize;
this->myArray = new int[maxCapacity];
for(int i = 0; i < maxCapacity; i++)
{
this->myArray[i] = rho.myArray[i];
}
return *this;
}
MyVector::MyVector(const MyVector& b)
{
maxCapacity = b.maxCapacity;
myArray = new int[maxCapacity];
for (int i = 0; i < maxCapacity; i++)
{
this->myArray[i] = b.myArray[i];
}
}
int MyVector::size() const
{
return vectorSize;
}
int MyVector::capacity() const
{
return maxCapacity;
}
void MyVector::clear()
{
delete [] myArray;
maxCapacity = 2;
myArray = new int[maxCapacity];
vectorSize = 0;
}
void MyVector::push_back(int add_Element)
{
if(vectorSize+1>maxCapacity)
{
maxCapacity = maxCapacity*2;
int* tmp = new int[maxCapacity];
for(int i=0; i <vectorSize; i++)
{
tmp[i] = myArray[i];
}
delete[] myArray;
myArray = tmp;
}
myArray[vectorSize] = add_Element;
vectorSize++;
}
int MyVector::at(int i) const
{
if(i >= vectorSize)
{
throw i;
}
else
{
return myArray[i];
}
}
ostream& operator<<(ostream& theStream, const MyVector& aVector)
{
for (int i = 0; i < aVector.size(); i++)
{
theStream << aVector.at(i);
}
return theStream;
}
And of course the Driver. I am unable to change the driver
#include <iostream>
#include "MyVector.h"
using namespace std;
// the printV function
// used to test the copy constructor
// parameter: a MyVector object
void printV(MyVector);
int main( )
{
cout << "\nCreating a vector Sam of size 4.";
MyVector sam( 4 );
cout << "\nPush 12 values into the vector.";
for (int i = 0; i < 12; i++)
sam.push_back(i);
cout << "\nHere is sam: ";
cout << sam;
cout << "\n---------------\n";
cout << "\nCreating a vector Joe of size 4.";
MyVector joe( 4 );
cout << "\nPush 6 values into the vector.";
for (int i = 0; i < 6; i++)
joe.push_back(i * 3);
cout << "\nHere is joe: ";
cout << joe;
cout << "\n---------------\n";
cout << "\nTest the overloaded assignment operator \"joe = sam\": ";
joe = sam;
cout << "\nHere is sam: ";
cout << sam;
cout << "\n---------------\n";
cout << "\nHere is joe: ";
cout << joe;
cout << "\n---------------\n";
// pass a copy of sam by value
printV(sam);//my problem is here! It changes the array size to a very large number
cout << endl;
system("PAUSE");
return 0;
}
void printV(MyVector v)
{
cout << "\n--------------------\n";
cout << "Printing a copy of a vector\n";
cout << v;
}
I think you are missing
vectorSize = b.vectorSize;
line in your copy constructor MyVector::MyVector(const MyVector& b)
I've been working on some code for an assignment and I'm having an issue with nested templated types.
I need the following code to create a 3 element array of 3 element arrays (sort of like int b[3][3]):
Array< Array<int> > b(3);
Here are the relevant parts of my Array.h:
template <class T>
class Array{
public:
Array() : size(0){ data = NULL; }
Array(int s) : size(s) { data = new T[size]; }
Array(const Array & a) : size(a.length()) {
data = new T[a.length()];
for(int i = 0; i < a.length(); ++i)
data[i] = a[i];
}
~Array(){ delete[] data; }
T & operator[](int i) {
if (i >= 0 && i < size){
return data[i];
} else {
throw ArrayOutOfBounds(i);
}
}
T operator[](int i) const{
if (i >= 0 && i < size){
return data[i];
} else {
throw ArrayOutOfBounds(i);
}
}
Array<T> & operator=(const Array<T> &a){
if(this == &a) return *this;
delete[] data;
data = new T[a.length()];
for(int i = 0; i < a.length(); ++i)
data[i] = a[i];
size = a.length();
}
int length() const { return size; }
// Members
private:
int size;
T * data;
}
Update 6/1 the full driver code:
// Test driver for generic Array object with assignment and bounds checking
#include "Array.h"
int main() {
Array<int> a1(10);
for (int i = 0; i < a1.length(); ++i)
a1[i] = i * i;
Array<int> a2 = a1;
try {
for (int i = 0; i <= a2.length(); ++i)
cout << a2[i] << " ";
cout << endl;
}
catch (const ArrayOutOfBounds & e) {
cout << endl << "ArrayOutOfBounds index=" << e.index << endl;
}
Array< Array<int> > b(3);
for (int i = 0; i < b.length(); ++i) {
for (int j = 0; j < b[i].length(); ++j)
b[i][j] = i*b[i].length() + j;
}
for (int i = 0; i < b.length(); ++i) {
cout << "b[" << i << "]= ";
for (int j = 0; j < b[i].length(); ++j)
cout << b[i][j] << " ";
cout << endl;
}
Array<const char *> c(3);
c[0] = "moe"; c[1] = "curly"; c[2] = "larry";
Array<const char *> d(10);
d = c;
for (int i = 0; i < d.length(); ++i)
cout << "d[" << i << "]=" << d[i] << " ";
cout << endl;
return 0;
}
Expected output:
0 1 4 9 16 25 36 49 64 81
ArrayOutOfBounds index=10
b[0]= 0 1 2
b[1]= 3 4 5
b[2]= 6 7 8
d[0]=moe d[1]=curly d[2]=larry
Update 6/2
Per Guillaume's solution, here is the resize method I used:
Array<T> & resize(int newsize){
delete[] data;
data = new T[newsize];
size = newsize;
for(int i = 0; i < size; ++i)
init(data[i], size);
}
Recursive resizing works for higher dimensions, such as Array< Array< Array<int> > > q(3);
Based on the code, you pasted, this should not crash. Did you forget the destructor? You should have a destructor that deletes the memory. When you have one, you need to make sure that data is initialized to nullptr (or NULL) so it does not crash when deleting an empty array.
But your approach is confusing. Is Array size supposed to be determined at runtime or at compile time? int b[3][3] is determined at compile time. If you want that, you should make the size a template argument like std::array in C++11, see http://en.cppreference.com/w/cpp/container/array
If you want to detemrine the size at runtime, you'll need a resize method to determine the size of the the 2nd dimension.
EDIT:
Based on the driver code, you need to do something different in the constructor (passing the int to T if T is an Array). To be quite honest, this seems almost like a bug. This kind of specification makes it really hard to describe what the constructor do (call the default ctor for all types T except for Array)
I'd something like this:
private:
template <typename U>
void init(U&, int) {}
template <typename U>
void init(Array<U>& a, int sz)
{
a.resize(sz);
}
public:
Array(int s) : size(s) {
data = new T[size];
for (int i = 0 ; i < size; ++i) {
init(data[i], s);
}
}
It works but this is ugly. If you can use C++11, you can something nicer with std::enable_if