Firstly I wanted to say this is a HW assignment and I just have questions in regards to the errors I'm facing
I made a vector template with an insert function that adds a data_type to the end of a dynamic array. This is what I have currently.
// Insert the value at the specified index by moving the tail
// when Size = Capacity the Vector has to be reallocated first
// to accomate the new element
void Insert(const DATA_TYPE& value, int index){
// If the Capacity is not large enough then ...
// allocate large vector
if (Size >= Capacity){
// 0. Let's boost the capacity
Capacity += CAPACITY_BOOST;
// 1. Allocate new larger vector
DATA_TYPE* newData = new DATA_TYPE[Capacity];
// 2. Copy from old Data into the newData
for( int i=0; i< Size; i++)
newData[i] = Data[i];
// 3. Delete the old Data
delete[] Data;
// 4. Replace old Data-pointer with the newData pointer
Data = newData;
}
// Move the tail
for(int i=index; i<Size;i++){
Data[i+1] = Data[i];
}
// Insert
Data[index] = value;
Size++;
}
DATA_TYPE& operator[] (int index) const{
return *this[index];
}
Note: Using Private Variables: Size, Capacity, Data(stores the dynamic array)
I'm pretty sure I've implemented the add or push_back function correctly. The problem is when ever I try to cout something like "cout << a[1]; " I get an error.
while compiling class template member function 'int &Vector<DATA_TYPE>::operator [](int) const'
with
[
DATA_TYPE=int
]
see reference to class template instantiation 'Vector<DATA_TYPE>' being compiled
with
[
DATA_TYPE=int
]
error C2440: 'return' : cannot convert from 'const Vector<DATA_TYPE>' to 'int &'
with
[
DATA_TYPE=int
]
There should be 2 versions of your operator[]:
const DATA_TYPE& operator[] (int index) const;
DATA_TYPE& operator[] (int index);
What you have is a weird combination of the two.
You should also be returning
return Data[index];
Returning (*this)[index]; would result in an infinite recursive call (well, not infinite, you'll get a stackoverflow before that).
There are three problems here:
Operator precedence. *this[index] is parsed as *(this[index]), while you meant (*this)[index].
You're returning a mutable reference to your data from a const method.
The definition of operator[] is circular. Returning (*this)[index] in operator[] would cause infinite recursion.
The operator[] function is declared to be constant, i.e. it can't change anything in the Vector object. But it returns a reference, which means that the returned value can be modified. These two contradicts each other.
This can be solved by either remove the const from the end of the function, or to not return a reference.
Related
I am trying to create a sorting function with the parameters being a pointer of a list and I am trying to access an element of the given list. Hopefully this code speaks for the problem better than I can:
void bubbleSort(std::vector<int> *L) {
unsigned int i = 0; int temp;
while(isSorted(*L)) {
if(i==L->size()-1) {
i = 0;
}
if(i<L[i]/*<-ERROR here.*/) {
temp = L[i+1]; // ERROR HERE
L[i+1] = L[i]; // ERROR HERE
L[i] = temp; // ERROR HERE
}
}
}
You don't need to painfully dereference every individual use of L (and indeed doing so is error-prone, as you've demonstrated by missing one in your answer).
Instead, just write:
void bubbleSort(std::vector<int> *Lptr) {
auto &L = *Lptr;
and keep the rest of the code the same.
NB. It would be even better to change the function itself, to
void bubbleSort(std::vector<int> &L) {
as it should have been written in the first place, but I'm assuming there's some artificial reason you can't do that.
The function accepts a pointer to an object of type std::vector<int>.
void bubbleSort(std::vector<int> *L) {
To access the original vector using the pointer, you can write either *L or L[0]. That is, both expressions yield an lvalue reference of type std::vector<int> & to the vector.
To get the i-th element of the vector using the subscript operator through the pointer, you can write either (*L)[i] or L[0][i],
However, in this if statement:
if(i<L[i]/*<-ERROR here.*/) {
You are trying to compare the variable i of type unsigned int to the object L[i] of type std::vector<int>. When i is not equal to 0, this yields a non-existent object of the vector type.
It seems you mean something like the following instead:
if ( (*L)[i] < (*L)[i+1] ) {
or:
if ( L[0][i] < L[0][i+1] ) {
or, vice versa:
if ( L[0][i+1] < L[0][i] ) {
Depending on whether the vector is sorted in ascending or descending order.
Pay attention to the fact that there is no sense in declaring the parameter as a pointer to a std::vector<int>. The function would be much clearer and readable if it accepted the vector by reference instead:
void bubbleSort(std::vector<int> &L) {
In this case, the if statement would look like this:
if ( L[i] < L[i+1] ) {
Although I prefer to change the source code as other answer. But, for this question, you can use ->at() function to access the element in a vector pointer.
if(i<L->at(i)) {
temp = L->at(i+1);
L->at(i+1) = L->at(i);
L->at(i) = temp;
}
I am still perfecting the art of posting here so bear with me, I will edit and fix anything suggested!
I have a homework that requires me to create functions that manipulate vectors. The "catch" is that all the data passed to the function is passed by reference to this struct:
struct Vector { // this struct must stay as is
int sze = 0; // "size" took out i for compatability
int capacity = 0;
int * data = nullptr ;
}a,b,c;
i.e.
void construct_vector ( Vector& v, int size= 0, int initVal= 0);
The problem that I am having is in the function construct_vector() I have to, you guessed it, construct a vector and use int* data to point to the vector on the heap? I am not positive about that last part). I just know I have to use the int pointer to point to the vector created within the construct function, and cannot for the life of me figure out how to do that.
An example of what I am trying:
void construct_vector ( Vector &v, int size, int initVal){
std::vector<int> t(size,initVal);
*v.data = &t ; // ERROR: Assigning to 'int' from incompatible type 'std::vector<int> *'
v.capacity = size; //
v.sze = size;
for (int i=0; i < t.size(); i++){
/* I originally tried to implement a
dynamic int pointer here but I cannot change int* data
to int*data[sze] within the struct*/
}
}
The reason int * data must point to the vector is because the data is passed to the subsequent functions by reference to struct member v:
void destroy_vector ( Vector & v );
void copy_data ( Vector & v );
Edit: My problem was that I misunderstood the objective of my assignment but I think the answers I received can really help people understand dynamic memory and how it should be used within functions. So I am going to leave everything as is!
You have two problems here:
std::vector<int> t(size,initVal);
*v.data = &t ; // ERROR: Assigning to 'int' from
First, *v.data and &t are different types, one is int, the other is a pointer to a vector of ints.
You can get it compile with (but you SHOULD NOT, see the second problem)
v.data = t.data();
The other problem is the vector is local to the function. As soon as the function returns, your pointer will dangle.
So the right solution for your problem is using a dynamic array:
v.data = new int[size];
Don't forget to delete[] it in the struct's destructor when you are done using it:
delete [] data;
Instead of
std::vector<int> t(size,initVal);
*v.data = &t ;
You need
v.data = new int[size];
To fill up the object with the input value, use
for ( int i = 0; i < size; ++i )
{
v.data[i] = initVal;
}
You can use std::fill to make your code a bit simpler.
std::fill(v.data, v.data+size, initVal);
Make sure to follow The Rule of Three when you manage dynamic memory yourself.
I was wondering.. Whenever I deal with arrays, when I have to cut it, or sort it, or anything, and then return it, I pass it to the void function like f(array, length, newarray) and in the function declaration I have void f(T *array, int length, T *&new array).
Is there a better way to do this?
Here's some code, I want to remove repeats from an array:
template<class T>
void eliminate(T *niz, int duzina, T *&podniz)
{
int ind;
podniz = new T[duzina];
for (int i = 0; i<duzina; i++)
{
ind = 0;
for (int j = i; j<duzina; j++)
{
if (niz[i] == niz[j])ind++;
}
if (ind == 1)podniz[nova++] = niz[i];
}
}
As already noted in the comments, you really want std::vector.
The main problem with your code is that there is no way to tell how many of the output elements are actually initialized. And accessing uninitialized elements is Undefined Behavior, so you are returning a time bomb to the caller.
With std::vector<T> eliminate(std::vector const&), there's no such doubt. The returned vector has exactly .size() elements.
Vector is also exception-safe. Your code will leak memory if the copy constructor of T throws, e.g. on a std::bad_alloc.
Sure. You can use pointers and pass the array by reference to the function.
Then manipulate the array and return from the function with void type i.e no need of returning the array as it is passed by reference.
I overloaded the operator[] for my DataStructure class to return the indicated value, as follows:
T& operator[](int i) {
return m_array[i];
}
But when I loop over the values, I want to print them as follows:
for (int i = 0, s = stack->size(); i < s; ++i) {
printf("%7i %5i\n", i, stack[i]);
}
Since I created the generic DataStructure as an integer Stack (derived class)
stack = new Stack<int>(STACKSIZE);
But this does not work. I expected every item on the stack to be int, but the compiler says I cannot typecast Stack<int> to int, even though I'm not trying to typecast an Stack!!!
What am I missing? Also, I can not use
printf("%7i %5i\n", i, (int)stack[i]);
Since for some reason it "is not" an integer type.
If stack is a pointer to a Stack<int>, then stack[i] doesn't call the stack's operator[]. It treats the pointer as a pointer to the first element of an array and tries to index into that array. Either don't make it a pointer:
Stack<int> stack(STACKSIZE);
or dereference the pointer:
(*stack)[i]
C++ newb here. I'm trying to write my own implementation of an array using only pointers, and I've hit a wall I don't know how to get over.
My constructor throws this error
array.cpp:40:35: error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
When my array initializes I want it to free up all the spaces in the array for ints.
Array::Array(int theSize){
size = theSize;
int *arrayPointer = new int;
int index = 0;
while(theSize > index){
*(arrayPointer + index) = new int; //This is the trouble line.
++index;
}
}
What am I doing wrong stackoverflow?
arrayPointer points to a single int, it does not point to an array of int*, which this line would require:
*(arrayPointer + index) = new int;
but the type of *(arrayPointer + index) is an int, hence the compiler error.
To allocate an array of int:
int* arrayPointer = new int[size];
If this is intended to initialise a member variable then:
arrayPointer = new int[size];
otherwise arrayPointer would be local to the constructor. As the class now has a dynamically allocated member you need to either implement both copy constructor and assignment operator or prevent copying (see What is The Rule of Three?). Remember to delete[] arrayPointer in the destructor.
Just mentioning std::vector<int>, even though this is a learning exercise.
Do as follows:
#include <cstddef>
template <typename T>
class Array
{
public:
T* const arrayPointer; // arrayPointer can't be reallocated
const size_t size; // size can't change
Array(const int theSize) : arrayPointer(new T[theSize]),
size(theSize) {}
~Array() {
delete[] arrayPointer;
}
private:
Array(const Array& other) {} // forbid copy
Array& operator= (const Array& other) {} // forbid assignment
} ;
Why to use template <typename T>? So you can have an array of any type.
Why to use new T[ theSize ] ? So you can allocate theSize elements at the same time.
Why to use : arrayPointer( new T[ theSize ]) ? So in case allocation fails (due to big theSize) the object fails without initialization. It is callled RAII.
Why to use delete [] arrayPointer ? Because you used new[] and you have to deallocate the whole array.
Why those const's? To avoid anyone changing the size of the array and making the fields inconsistent.
What are these private methods? They are forbiding copies, so no one can make array1 = array2; delete array2;, what would deallocate the arrayPointer of array1.
Usage (it will allocate array of 10 int:)
Array< int > arr( 10 ) ;
Access:
arr.arrayPointer[ 0 ] = 5 ;
Note - you can access arrayPointer at the cells of range 0..9. You can add operator[] to your class in order to avoid using arrayPointer and to use arr[ 0 ].
The line you mentioned is trying to set a int* into a int var => Dereferencing a int* provide a int :
*(arrayPointer + index) // is a int
Anyway you are moving in memory (and dereferencing memory) you haven't reserved. So you can access a protected memory zone by doing this instruction.
Replace all your constructor with:
Array::Array(int theSize)
{
size = theSize;
arrayPointer = new int[theSize]; // Replace your local var with a member one. Else you will lose your array ;)
}