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]
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'm getting started with c++ and I have this method where I overload the subscript operator "[ ]" but I need to return an array from that method, In the method, I'm trying to return a sub array from a bigger array but I can't seem to return a whole array since I can only return a single element from an array, how can I get the method to return an entire array?
For example:
int& PagedArray::operator [] (int position){
if(position == 0){
for(int i = 0; i < 256; i++){
pageArray[i] = completeArray[i];
//cout << to_string(i) + " " + to_string(pageArray[i]) << endl;
}
return pageArray[0] ;
}
}
When I try to return I can only get a specific element from the array pageArray, but I need to return pageArray, how can I get that done?
thanks
I need to return an array from that method
int& PagedArray::operator [] (int position)
The return type that you've given for your function does not match what you need to return. This function returns a reference to an integer; not an array.
A problem with what you need is that you cannot return an array in C++; that's just not allowed in the language. That is to say, return type cannot be an array. There's a fairly easy way to get around that however: You can return instances of classes and you can store arrays as member of a class. There is a template for such array wrapper class in the standard library. It's called std::array.
Here is an example of returning a sub-array:
constexpr std::size_t page_size = 256;
std::array<int, page_size>
PagedArray::operator[] (int){
std::array<int, page_size> page;
std::copy(completeArray, page);
return page;
}
Given that you originally tried to return a reference, you may be looking for a way to avoid copying the sub-array by using indirection. A problem is that the sub array doesn't exist anywhere prior to calling the function and you cannot return a reference to something that you create in the function.
Instead of returning reference to small array, you can return a subrange pointing to the big array. There are actually more than one option in the standard library. There's a general purpose std::ranges::subrange and also std::span that is specific to contiguous ranges. I recommend using the more specific type assuming you aren't templetising the type of the big container. Example:
std::span<int, page_size>
PagedArray::operator[] (int){
return {completeArray, page_size};
}
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 was playing through c++ and trying to understand vector and its signature .
In below method printPrimes I need to use pointer with address of why ?
Is vector<int> &primes not enough as from main method printPrimes is already sending address .
void printPrimes(long long l, long long r, vector<int>* &primes) {
// some code
}
vector<int>* sieve() {
vector<int> *prime = new vector<int>();
return prime;
}
int main() {
vector<int> *primes = sieve();
printPrimes(l, r, primes);
return 0;
}
I need to use pointer with address of
Here, & does not mean "address of"; it means the type "reference to".
It's clearer if you write it not like this:
vector<int>* &primes
but like this:
vector<int>*& primes
Though the choice of whitespace is artificial, that better documents that this & is "part of the type".
Have some types:
std::vector<T> = A vector of Ts
std::vector<T>& = A reference to a vector of Ts
std::vector<T>* = A pointer to a vector of Ts
std::vector<T>*& = A reference to a pointer to a vector of Ts
std::vector<T>*** = A pointer to a pointer to a pointer to a vector of Ts
std::vector<T>**& = A reference to a pointer to a pointer to a vector of Ts
…and so forth.
As for why you need a vector<int>*& for printPrimes to do its job, we could not tell you without actually being able to see it. I will say that it seems unlikely it needs a pointer at all, and that if it wants to modify that pointer it's going to cause problems with the new and delete in the calling scope.
In fact, all that dynamic allocation is completely pointless and only complicates things.
The following was likely intended instead:
void printPrimes(long long l, long long r, vector<int>& primes) {
// some code
}
vector<int> sieve() {
vector<int> prime;
return prime;
}
int main() {
vector<int> primes = sieve();
printPrimes(l, r, primes);
}
vector<int>* &primes parameter has to be read this way:
Reference to a pointer of vector of int
and not
Address of a pointer of vector of int (which, you are right, would be useless)
Passing by reference allows to directly manipulate any instance outside of scope (like with pointers, but a safer way since a reference cannot be nullptr, and its existence is auto-managed (no need to delete)).
In c++ & in function parameter used to pass parameter by reference. vector<int>* &primes declares primes to be a reference to a pointer to vector<int>.
If printPrimes means to print only the vector passed to the function then the signature
void printPrimes(long long l, long long r, vector<int> &primes);
can also do the job.
Reference to a pointer is needed when the pointer passed to the function is need to be modified and it's effect is expected to seen in the caller function.
void foo(int*& p){
p = new int[10];
// rest of the code
}
if a function bar is calling foo like
void bar(/* some parameters */){
// ...
int *p;
foo(p);
// rest of the code
}
foo is modifying the pointer itself and this modification will be seen to bar also and memory allocated to p can be accessed from bar.
I'm curious as to why the following code doesn't work. In particular, the compiler seems to be viewing *(result + i) as a gVector3 type as opposed to a float. But result is a pointer to a float array right? So wouldn't dereferencing a pointer return a float? You can assume that gVector3 and gMatrix3 are defined.
/* returns the column vector at index i */
gVector3 gMatrix3::getColumn(unsigned int index) const{
gVector3* result = new gVector3();
for (int i = 0; i < 3; i++){
*(result + i) = data[i][index];
}
return *result;
}
If gVector3 is a class, then it probably overloads operator[], which is what you should use. Otherwise you're performing pointer arithmetic on the object itself. Try this:
(*result)[i] = data[i][index];