0

Suppose you have an array of objects in C++ and you remove one of the objects from the array. When is that object's destructor called? Since C++ does not have automatic garbage collecting, it would seem strange if the destructor was called right after being removed from the array. But does the object stay allocated until the array goes out of scope? That seems like it would lead to memory leaks.

Edit:

Instead of "remove" how about setting one of the elements of the array to a different object.

Also, what does happen when an element is removed from a std::vector?

murrekatt
  • 5,961
  • 5
  • 39
  • 63
Daniel
  • 6,595
  • 9
  • 38
  • 70

4 Answers4

2

You can't "remove one of the objects from the array." Arrays have fixed size. All the contents are constructed at the time the array is created and destroyed when the array itself is destroyed.

If you merely assign a new value to an array element, then you're invoking the object's = operator, and it behaves no differently than if you had a simple standalone variable and assigned a new value to it. No objects are necessarily constructed or destroyed. If there's any new object, it's from a temporary that the compiler generates for the right side of the assignment statement. After the statement has completed, the temporary object is destroyed. The object in the array remains intact.

When you remove an item from a vector, its destructor is called, as you'd expect, and the later elements are shifted down to fill in the gap.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
1

When you declare a C++ array, it constructs all of the objects on the stack, and they stay there until the array itself is deleted:

std::string ArrayOfStrings[10]; //There are now ten strings here

Objects can't be "removed" from this kind of array. When ArrayOfStrings goes out of scope, it automatically deletes all the strings in the array. If you edit an object in this array, that object itself is changed. You actually changed the string itself, not some pointer or reference.

If you have an array of pointers, then C++ constructs all of the pointers, but you have to manage what they point at yourself:

std::string* ArrayOfPointersToStrings[10];

You can manually delete strings that the pointers in the array point to, but you have to do all of that yourself. When ArrayOfPointersToStrings goes out of scope, it WILL NOT delete anything the strings point at. If you edit a pointer without deleting it first, that's a memory leak, and that's bad.

If you have a std::vector, C++ constructs only some objects depending on how you construct it:

std::vector<std::string> VectorOfStrings(10);

This creates a dynamic array of strings. It is possible to remove objects from a vector, in which case the vector instantly deletes it and rearranges the rest for you. If you edit an object in this array, that object itself is changed. You actually changed the string itself, not some pointer or reference.

To clarify comments:

char *myLiteral = "APPLE";
//"APPLE" is an immutable string, myLiteral points at it.
std::string s= myLiteral; 
std::string t = myLiteral;
//s and t each makes a _seperate_ _mutable_ copy of "APPLE"
s[3] = '?'; 
//s is now "APP?E", because we just changed the L.  NO COPY WAS DONE. 
std::cout << t[3];
//displays "L", because t's copy was never changed.
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • But isn't std::string immutable? – Daniel Aug 24 '11 at 19:18
  • @Daniel: `string s = "hello"; s = "world";` The value of `s` is now `"world"`. http://codepad.org/a8B4SoWM – Bill Aug 24 '11 at 19:20
  • Also, if you did something like `std::string *a; *a = "hello";`, you wouldn't have to manually delete a. – Daniel Aug 24 '11 at 19:21
  • @Bill I know that, but that is because a new string object was created that contains the characters "world". – Daniel Aug 24 '11 at 19:22
  • a) yes, you'd have to `delete a;`. b) it's the same object, it's just using a (probably) different internal buffer to store the text. – Bill Aug 24 '11 at 19:23
  • @Daniel: no, in C++, no built-in objects are immutable. You can change anything. – Mooing Duck Aug 24 '11 at 19:24
  • @Bill Are you very sure about that? My impression is that std::string objects are immutable. – Daniel Aug 24 '11 at 19:25
  • @Daniel: I take it back, string literals are immutable, but std::string makes a mutable copy, so it almost never comes up. – Mooing Duck Aug 24 '11 at 19:26
  • @Bill why would I have to `delete a;`? Isn't `delete` used for dynamically allocated memory on the heap? – Daniel Aug 24 '11 at 19:29
  • @Daniel: Perhaps you're thinking about C#? In C++, you can do this, for instance: `string s = "Hello World!"; s[0] = 'Y'; cout << s;` produces `Yellow World!`. – Bill Aug 24 '11 at 19:29
  • Well, you omitted the `a = new std::string`, which is required. Otherwise you're getting undefined behavior when you dereference a to assign "hello". So once you add in the `new` you'll need the `delete`. http://codepad.org/DMbG67fM – Bill Aug 24 '11 at 19:31
  • @Daniel: `std::string *a;` makes a pointer to a string, but you haven't made a string yet. `*a = "hello";` assigns the word hello to... nothing. There's no string. This will crash. – Mooing Duck Aug 24 '11 at 19:33
  • @Bill: Duh. I feel like an idiot. This week has been too long. – Daniel Aug 24 '11 at 19:34
  • @Mooing: Yeah I get it now. I should have just taken a nap before posting this question. – Daniel Aug 24 '11 at 19:35
  • @Daniel: don't worry about it. Exactly 50% of my questions I ended up answering myself because I didn't think it through before posting, but did after. – Mooing Duck Aug 24 '11 at 19:45
0

For a standard container like std::vector, by the time the remove method completes the object has been destructed.

For a "c-style" array an object itself will last as long as it would if it wasn't in an array.

The lifetime of an object depends on where the object was allocated. If it's on the stack it's deallocated when the current scope ends, if it's on the heap then it will not be deallocated until delete is called on it. The last case leads to memory leaks if the object is never freed.

  • And what happens if I have an array, and I replace one of the elements in it. For example: `a[0] = myObject();` a[0] = myOtherObject();` When does the myObject instance get destructed? – Daniel Aug 24 '11 at 19:10
  • @Daniel, the myObject instance will be destroyed when it is overwritten by the myOtherObject instance. – john Aug 24 '11 at 19:22
0

You can't remove objects from a vanilla C++ array. When you declare an array of a certain size, regardless of whether on the stack or heap, assuming the allocation was successful, enough memory is allocated to create N objects of that type and they are created using whatever contructor is appropriate.

Using an assignment operator to copy the contents of the RHS to an object in the array generally does nothing to the object on the RHS. The memory in the array just gets overwritten. No new objects are created or removed (unless you do something like obj1 = obj2 = obj3 which is a whole 'nother can of worms...)

Poodlehat
  • 360
  • 1
  • 2
  • 9