As a Java developer I have the following C++ question.
If I have objects of type A and I want to store a collection of them in an array, then should I just store pointers to the objects or is it better to store the object itself?
In my opinion it is better to store pointers because: 1) One can easily remove an object, by setting its pointer to null 2) One saves space.
In Java, arrays are full-fledged objects, and, like any other object in a Java program, are created dynamically. Array references can be used anywhere a reference to type Object is called for, and any method of Object can be invoked on an array.
An array of references is illegal because a reference is not an object. According to the C++ standard, an object is a region of storage, and it is not specified if a reference needs storage (Standard §11.3. 2/4). Thus, sizeof does not return the size of a reference, but the size of the referred object.
A variable of array type holds a reference to an object. Declaring a variable of array type does not create an array object or allocate any space for array components. It creates only the variable itself, which can contain a reference to an array.
Storing Objects in an arrayYes, since objects are also considered as datatypes (reference) in Java, you can create an array of the type of a particular class and, populate it with instances of that class.
You can't put references in an array in C++. You can make an array of pointers, but I'd still prefer a container and of actual objects rather than pointers because:
The only times I'd advocate putting pointers (or smart pointers would be better) in a container (or array if you must) is when your object isn't copy construable and assignable (a requirement for containers, pointers always meet this) or you need them to be polymorphic. E.g.
#include <vector>
struct foo {
virtual void it() {}
};
struct bar : public foo {
int a;
virtual void it() {}
};
int main() {
std::vector<foo> v;
v.push_back(bar()); // not doing what you expected! (the temporary bar gets "made into" a foo before storing as a foo and your vector doesn't get a bar added)
std::vector<foo*> v2;
v2.push_back(new bar()); // Fine
}
If you want to go down this road boost pointer containers might be of interest because they do all of the hard work for you.
Assigning NULL
doesn't cause there to be any less pointers in your container/array, (it doesn't handle the delete
either), the size remains the same but there are now pointers you can't legally dereference. This makes the rest of your code more complex in the form of extra if statements and prohibits things like:
// need to go out of our way to make sure there's no NULL here
std::for_each(v2.begin(),v2.end(), std::mem_fun(&foo::it));
I really dislike the idea of allowing NULL
s in sequences of pointers in general because you quickly end up burying all the real work in a sequence of conditional statements. The alternative is that std::vector
provides an erase
method that takes an iterator so you can write:
v2.erase(v2.begin());
to remove the first or v2.begin()+1
for the second. There's no easy "erase the nth element" method though on std::vector
because of the time complexity - if you're doing lots of erasing then there are other containers which might be more appropriate.
For an array you can simulate erasing with:
#include <utility>
#include <iterator>
#include <algorithm>
#include <iostream>
int main() {
int arr[] = {1,2,3,4};
int len = sizeof(arr)/sizeof(*arr);
std::copy(arr, arr+len, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// remove 2nd element, without preserving order:
std::swap(arr[1], arr[len-1]);
len -= 1;
std::copy(arr, arr+len, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// and again, first element:
std::swap(arr[0], arr[len-1]);
len -= 1;
std::copy(arr, arr+len, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
preserving the order requires a series of shuffles instead of a single swap, which nicely illustrates the complexity of erasing that std::vector
faces. Of course by doing this you've just reinvented a pretty big wheel a whole lot less usefully and flexibly than a standard library container would do for you for free!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With