0

In my following program I tried to create a class similar to vector in c++. The function access in class Array is used to get element in array. The function pushback() is similar to push_back() function in vector and popback() is similar to pop_back() in vector. I am not able to delete last elements using popback() function. In popback() function delete [] arry seems to be the problem as it is not deleting all elements in arry.

Code:

#include <iostream>
#include <set>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <cmath>
#include <climits>
#include <cctype>


using namespace std;

class Array{
    public:
    int *arry;
    int sizeofarray;
    Array(){
     sizeofarray=0;
     arry = new int[sizeofarray];
    }
    int access(int index){
        return arry[index];
    }
    void pushback(int element){

         int *temparray= new int[sizeofarray+1];
         for(int i=0;i<sizeofarray;i++){
            temparray[i]=arry[i];
         }
         temparray[sizeofarray]=element;
         delete [] arry;
         arry= new int[++sizeofarray];
         for(int i=0;i<sizeofarray;i++){
            arry[i]=temparray[i];
         }
         delete temparray;
    }
    void popback(){
         int *temparray= new int[sizeofarray-1];
         for(int i=0;i<sizeofarray-1;i++){
            temparray[i]=arry[i];
         }
         delete [] arry;
         sizeofarray--;
         arry= new int[sizeofarray];
         for(int i=0;i<sizeofarray;i++){
            arry[i]=temparray[i];
         }

         delete temparray;

    }
    int sizey(){
        return sizeofarray;
    }
};
int main(){
    Array myfirstvector;

   //I assigned following to create an example of my problem

    myfirstvector.pushback(9);
    myfirstvector.pushback(2);
    myfirstvector.pushback(3);
    myfirstvector.pushback(4);
    myfirstvector.pushback(7); //This element is not deleting 
    myfirstvector.popback();
    myfirstvector.popback();

    cout<<myfirstvector.access(0)<<" "<<myfirstvector.access(1)<<" "<<myfirstvector.access(2)<<" "<<myfirstvector.access(3)<<" "<<myfirstvector.access(4)<<" "
    <<myfirstvector.access(6)<<endl;
    cout<<"Size of array"<<myfirstvector.sizey()<<endl;
}

Output I get:

9 2 3 0 7 651317883
Size of array3

Output I expect:

9 2 3 garbagevalue grabagevalue garbagevalue
Size of array3

I tried modifying popback() function but still could not resolve my issue. I expect the popback() function to work similar to pop_back in vector.

Luke B
  • 2,075
  • 2
  • 18
  • 26
  • 2
    The second loops in the methods are overkill. Just assign `arry = temparray` and don't delete the last one. – 273K Apr 14 '23 at 16:03
  • 3
    You push 5 values, then you pop 2 values and then you display values 0 to 2 (which are valid) and values 3, 4 and 6 which are invalid, so what do you expect? – Jabberwocky Apr 14 '23 at 16:03
  • `delete temparray` -- Wrong form of `delete`. It should be `delete [] temparray;` As to creating a class similar to `std::vector`, I think you should work on getting the copy semantics correct for your `Array` class before implementing functions such as `pop_back` and `push_back`. Your class violates the [rule of 3](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). – PaulMcKenzie Apr 14 '23 at 16:05
  • @273K I tried what you have said but the behavior was so weird. I was getting garbage values for first few elements for some odd reason. – Kharinandan D N Apr 14 '23 at 16:06
  • The culprit is your naive and sloppy code that displays the vector content. Replace your code with this: `for (int i = 0; i < myfirstvector.sizey(); i++) { std::cout << myfirstvector.access(i) << " "; }`. There may be more problems though, I didn't check the rest of your code, which BTW is overly complicated and very inefficient. – Jabberwocky Apr 14 '23 at 16:07
  • @Jabberwocky I expect to display garbage values for the index 3, 4 and 6. – Kharinandan D N Apr 14 '23 at 16:11
  • Accessing a deleted object has undefined behaviour, part of that undefined behaviour is the object can appear to still be there – Alan Birtles Apr 14 '23 at 16:12
  • @KharinandanDN `9 2 3 garbagevalue grabagevalue garbagevalue` -- What is defined as a "garbage value"? The "garbage value" can be 0, 1, 2, -3432, 24352342, 17, etc. A `0` is just as garbage as `-4532432`. Just because the number "looks nice" doesn't mean it isn't "garbage". – PaulMcKenzie Apr 14 '23 at 16:14
  • @Jabberwocky I want my code to work like vector. If we try to access elements out of bound after 'pop_back()' , we get garbage value and not the value we assigned. I want my code to work in sameway. – Kharinandan D N Apr 14 '23 at 16:16
  • @KharinandanDN -- Again, *any value you see is garbage* if you attempt to access items outside the allocated space. What to you is a "garbage value"? – PaulMcKenzie Apr 14 '23 at 16:18
  • @PaulMcKenzie I don't want the element I assigned in garbagevalue. Try `myfirstvector.pushback(9); myfirstvector.pushback(2); myfirstvector.pushback(3); myfirstvector.pushback(4); myfirstvector.pushback(10); //This element is not deleting, It shows the assigned value myfirstvector.popback(); myfirstvector.popback(); ` – Kharinandan D N Apr 14 '23 at 16:19
  • 1
    @KharinandanDN -- You are failing to understand something fundamental when it comes to accessing elements out-of-bounds. Once you do that, you cannot rely on anything to be of any certain value. Also, when you access an item out-of-bounds with `std::vector`, there is no guarantee what the results will be. Your program could crash on accessing an out-of-bounds element, and not even produce a number. You are basically wasting time trying to get something that is undefined to act in a defined way. – PaulMcKenzie Apr 14 '23 at 16:19
  • @KharinandanDN Read this: https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope, it's about accessing local variables gone out of scope, but it also applies to accessing memory that is no loger your's. – Jabberwocky Apr 14 '23 at 16:20
  • You should add a destructor; Otherwise there's a memory leak. The simplest fix of the memory leak that wouldn't even require you to implement the destructor would be to change the type of `arry` to `std::unique_ptr` which would also allow you to implement `pushback` like this `auto newArray = std::make_unique(sizeofarray + 1); *std::copy(arry.get(), arry.get() + sizeofarray, newArray.get()) = element; ++sizeofarray; arry = std::move(newArray);` It also provides you with move semantics for `Array` "for free"... – fabian Apr 14 '23 at 16:21
  • Also, a `std::vector` does not shrink it's allocated size on `pop_back` by creating a brand new area of memory, while your code does. Your Array class is missing a `capacity` setting that goes along with `sizeofArray`. – PaulMcKenzie Apr 14 '23 at 16:25
  • @PaulMcKenzie "trying to get something that is undefined" but still how the value seems to be fixed to the value I assign every time. The behavior of that element seems to be defined right? – Kharinandan D N Apr 14 '23 at 16:27
  • @KharinandanDN -- Are you accessing the item out-of-bounds, yes or no? If it's yes, then the behavior is undefined. You could repeat this test 100 times with the same results, the behavior is still undefined. What if you take this code, compile it with different options (or another compiler), and the results no longer are what you expect? – PaulMcKenzie Apr 14 '23 at 16:29
  • 3
    @KharinandanDN no, it's undefined behaviour. It just _looks_ like defined behaviour. On another computer, another OS, with another compiler, etc. you might get another behaviour. Undefined behaviour includes "apparently working as I expect". – Jabberwocky Apr 14 '23 at 16:29
  • Note that `delete` does nothing but mark the memory available for reuse. – Jesper Juhl Apr 14 '23 at 16:30
  • @JesperJuhl debug versions of `delete` might overwrite freed memory with a special pattern that makes freed memory reuse easier to spot during debug. – Jabberwocky Apr 14 '23 at 16:31
  • @PaulMcKenzie I do get it but why do I get the value I assign every time, this behavior annoys me . – Kharinandan D N Apr 14 '23 at 16:33
  • If you want to have known garbage, you'll have to make your own garbage explicitly. For example: `int access(int index){ if (index < 0) return -666; if (index < sizeofarray) return arry[index]; return 999; }` – Eljay Apr 14 '23 at 16:34
  • @Jabberwocky So, do you suggest that my code is working fine to what I expect? – Kharinandan D N Apr 14 '23 at 16:36
  • @KharinandanDN -- *this behavior annoys me* -- `int access(int index) { if ( index >= sizeofarray ) { throw an exception; } return access[index]; }`. That is what a lot of debug runtimes for `std::vector` do. That is what your code should be doing. What if you decide to use your `Array` class for something bigger, and you have a bug in your code that calls `Array` with an invalid `index`? You want the client to be informed that the item is out-of-bounds, no? Why would you fool the client program into believing that the access is valid, when it isn't? – PaulMcKenzie Apr 14 '23 at 16:37
  • Please read https://en.cppreference.com/w/cpp/language/ub – Jesper Juhl Apr 14 '23 at 16:37
  • @KharinandanDN -- Also, what if I did this: `myfirstvector.pushback(651317883);`? How can you tell if that value is garbage or not? It was a value that was added by the user of the Array class explicitly, and not "garbage". That's why you can't call values "garbage" -- it works both ways, a "garbage value" can look "good", and a "garbage-looking value" could be completely valid. The only thing you can rely on is that the access was out-of-bounds, and if it is, all bets are off as to what lies there. – PaulMcKenzie Apr 14 '23 at 16:41
  • @PaulMcKenzie The problem is I am getting the exact value which is deleted and I don't need it as I use `delete [] arry`. If `delete [] arry` statement works fine, then I should not get the value I assigned right? – Kharinandan D N Apr 14 '23 at 16:47
  • @KharinandanDN *The problem is I am getting the exact value which is deleted* -- Once again, I'll ask you: `Are you accessing the item out-of-bounds, yes or no?` If it's yes, then there is no further thing to discuss. Second `delete[]`, as mentioned previously does not mean that the values go up into a puff of smoke and disappear. Were you expecting this? – PaulMcKenzie Apr 14 '23 at 16:48
  • @KharinandanDN The bottom line is that you have written a program which has undefined behaviour, and are complaining that it behaves in a way you do not want. But programs with undefined behaviour can legally behave in any way. In particular you cannot draw conclusions about what is or is not being deleted from a program with UB. – john Apr 14 '23 at 16:52
  • @KharinandanDN you put an apple into a trash can. Somewhat later you come back, you open the trash can and look into it. The apple might still be there, or the trash can may be empty because someone emptied it, or the trash can may be gone alltogether because someone has set fire to it, or whatever. – Jabberwocky Apr 14 '23 at 16:52
  • @KharinandanDN -- You buy a rope that the rope manufacturer says can hold up to 500 pounds. You tie 600 pounds to the rope, and the rope doesn't break. You then tell your friend to buy the same rope, he ties 600 pounds to it, and the rope breaks immediately. Who is at fault, you or the manufacturer? You broke the rules by tying too much weight, and you got the rope to "behave" (undefined behavior), but when your friend tried it, disaster. That in a real-world sense is what undefined behavior is all about. – PaulMcKenzie Apr 14 '23 at 16:55
  • @KharinandanDN If you want to check your Array code then change it so that it is an array of some class, called say `Item`. Then you can add a destructor to `Item` and print a message to the console from that destructor. That would be a valid way to check if all your elements are being deleted. – john Apr 14 '23 at 17:01
  • Once you break the rules of the language, the compiler is no longer under *any* obligation to generate sane code - it can do whatever it wants. That's what UB means - you broke the rules, now you get broken code (or maybe even working code - *anything* is ok - why is that so hard to understand?). – Jesper Juhl Apr 14 '23 at 17:22

0 Answers0