Set array of object to null in C++

56,907

Solution 1

Use pointers instead:

Foo *array[10];

// Dynamically allocate the memory for the element in `array[0]`
array[0] = new Foo();
array[1] = new Foo();

...

// Make sure you free the memory before setting 
// the array element to point to null
delete array[1]; 
delete array[0]; 

// Set the pointer in `array[0]` to point to nullptr
array[1] = nullptr;
array[0] = nullptr;

// Note the above frees the memory allocated for the first element then
// sets its pointer to nullptr. You'll have to do this for the rest of the array
// if you want to set the entire array to nullptr.

Note that you need to consider memory management in C++ because unlike Java, it does not have a Garbage Collector that will automatically clean up memory for you when you set a reference to nullptr. Also, nullptr is the modern and proper C++ way to do it, as rather than always is a pointer type rather than just zero.

Solution 2

So, forget Java here, it's not helping you. Ask yourself; what does it mean for an object to be null? Can an object be null? The answer is no, an object can not be null, but a reference (pointer in C++ terms) to one can be.

In java you have reference types, which are similar to pointers under the hood. However, you cannot set objects to null even in java, only references.

In C++ you have fully fledged objects and pointers and references to objects. A pointer to an object (or primitive type) can be null, but an object itself cannot.

So, when you create an array of Foo objects you have, well, an array of Foo objects. You don't have pointers, you have objects. If your array were an array of pointers to objects then yes, you could initialize them to null (nullptr in C++0x), i.e., they don't refer to a valid object.

Solution 3

Other way that you have is using one dynamic array of pointers of Foo like this:

Foo** array = new Foo*[10];// Pointer of array of pointers.

Then you can initialize all this pointers to objects Foo

for(int i=0;i<10;i++)
    array[i] = new Foo();// Give memory to pointers of object Foo in array

assign null to one item of array:

array[0] = 0;

I think that in C++, NULL is 0. This means it can even be assigned to an int or anywhere a 0 is acceptable. Conventionally, it's only used with pointers.

For delete this memory:

for(int i=0;i<10;i++)
    delete array[i];

and finally

delete[] array;

Code Example:

#include <iostream.h>
#include <stdio.h>
class Foo
{
  private:
    int a;
  public:
    Foo()
    {
      a = 0;
    }
   void Set_V(int p){a = p;}
   int Get_V(){return a;}
};

int main()
{
  Foo **array = new Foo*[10];
  for(int i=0;i<10;i++)
   {
     array[i] = new Foo();
   }

  //array[0] = 0;
  for(int i=0;i<10;i++)
    array[i]->Set_V(i);
  for(int i=0;i<10;i++)
    cout<<array[i]->Get_V()<<endl;
  for(int i=0;i<10;i++)
    delete array[i];
  delete[] array;
  return 0;
}

Solution 4

so is there away to "remove" an element in the array without creating a new one? i.e making a hole in the array of some sort?

In C++, if you have an array:

Foo array[10];

Then all 10 elements will be default-constructed. In general, there's no concept of array elements being in use vs. "removed". One way to track this idea is to make having actual values in the array elements optional, as in:

boost::optional<Foo> array[10];

You can read about the boost library's optional<> library at http://www.boost.org/doc/libs/release/libs/optional/

For the sake of documenting alternatives, I'll cover a hideous one. You could call the destructor on one of the elements: array[3].~Foo(); This is very dangerous as when the array itself goes out of scope, the destructor for each element will be called, and a precondition for that is to have a properly constructed object, so you have to be sure to have constructed a Foo in that element again beforehand (using "placement" new). There is nothing in the array itself that will help you keep track of which elements have had their destructors called by you - you'd need to track that yourself (having some record of this inside the objects would probably work in practice, but accessing the object after destruction is undefined behaviour). You'd need to be very careful that in all code paths - including those due to exceptions - you tracked the momentarily unused array elements. You really don't want to do this.

If your concern is to remove an element from the array to save memory, then use smart pointers:

shared_ptr<Foo> array[10];

You can then control specific array elements independently, with only still-populated elements being destructed when the element goes out of scope. Suitable smart pointers are available in boost or C++11, or you could use std::auto_ptr<> but should carefully read about its semantics beforehand to see if it's suitable and how to safely use it.

Separately, if there's a Foo::operator=(Some_Type*) then you could set array[3] = NULL;, and it would do whatever that assignment operator did to array[3]. Still, if Foo is not a pointer, it is probably a bad idea for it to allow someone to assign NULL to it.

Share:
56,907
Chin
Author by

Chin

(your about me is currently blank) click here to edit

Updated on October 14, 2020

Comments

  • Chin
    Chin over 3 years

    Suppose I have an array of objects of type Foo in C++:

    Foo array[10];
    

    In Java, I can set an object in this array to null simply by:

    array[0] = null //the first one
    

    How can I do this in C++?

  • Ed S.
    Ed S. over 11 years
    I see no dynamic allocation here, though it makes sense that you assume there will be. However, this is wrong; delete array[0]. Sure, that cleans up after the first element, but what about the others? I think it's best to be very clear when dealing with a beginner. The OP may take that to mean that delete array[0] is all you need, which is wrong.
  • Chin
    Chin over 11 years
    so in my original case, ie an array of Foo object, is there a way to delete one of them?. I think it doesn't make sense, right?
  • Ed S.
    Ed S. over 11 years
    @Chin: It doesn't make sense, and be careful with your terminology here' delete has a very specific meaning in C++, i.e., deallocating dynamically allocated memory. I think there is probably a better way to solve your problem here, but you'd need to expand on the question a bit.
  • Chin
    Chin over 11 years
    so is there away to "remove" an element in the array without creating a new one? i.e making a hole in the array of some sort?
  • Tony Delroy
    Tony Delroy over 11 years
    "and finally delete array" should be delete[] array... but you haven't explained why the array of pointers itself should be dynamically allocated... would appear unnecessary hassle.
  • deinier
    deinier over 11 years
    yes, you are right, delete[] array; By the way, it is other way to do that. I did not say that it is the only way and the difference is that I have one pointer to one array of Foo's pointers.
  • Ed S.
    Ed S. over 11 years
    @Chin: No, arrays are fixed in size at compile time. It seems to me that you really need a map structure, a vector, or (bad choice most likely) an array of pointers.
  • Tony Delroy
    Tony Delroy over 11 years
    "assign null to one item of array: array[0] = 0;" - better delete it first, or you leak the memory and any other resources the Foo might be managing. +1 for a good effort at being thorough.
  • deinier
    deinier over 11 years
    yes, you are right. I only answer how use null. Right now I am running one example I have and I want to share with everybody. Maybe it helps. I am new here and I have doubt how post code.
  • Tony Delroy
    Tony Delroy over 11 years
    If you indent code by 4 spaces it will be recognised and formatted as code. For code in the middle of a non-code sentence, you can use back-ticks (single left quotes) around the code, looks like this: "the virtual keyword". Welcome!