Design decision for operator[] in OwnedArray<Objectclass>


#1

Hi,

 

can somebody explain to me (with still limited C++11-background), why the []-operator in the OwnedArray - class returns a pointer rather than an object of the object class ? I just ask, because I thought it would be out of the norm of normal array-behaviour.

A link, which hints me into the right direction suffices.

 

Thank you well,

 

L


#2

If you wanted a copy of an object, you should have a list of stack objects that support copying (like... juce::Array<> or std::vector<> with a class type that has copy semantics!)

And you could even make a copy of the returned result from OwnedArray<>::operator[], assuming the object has a copy constructor, and the return type isn't null.

The point of an array with owned objects is to store a list of objects that don't have copy semantics - new'ed ones, alternatively...


#3

Agree with everything in the previous answer - expanding upon this:

The key information is in the Owned Array description:

"This holds a list of pointers to objects, and will automatically delete the objects when they are removed from the array, or when the array is itself deleted. Declare it in the form: OwnedArray<MyObjectClass> ..and then add new objects, e.g. myOwnedArray.add (new MyObjectClass()); After adding objects, they are 'owned' by the array and will be deleted when removed or replaced."

So the OwnedArray manages their lifetime of the objects that it contains (as pointers) that the user created on the heap - it does not contain copies of these objects. Hence the natural object to return is a pointer. A standard array class like std::vector<T> contains copies of the objects that are added to it and hence the natural object to return is a reference (T&) to the actual object in the vector.

Some useful terms to know are "intrusive" and "non-intrusive" applied to containers:

http://www.boost.org/doc/libs/1_35_0/doc/html/intrusive/intrusive_vs_nontrusive.html

"...in C++ non-intrusive containers store copies of values passed by the user...On the other hand, an intrusive container does not store copies of passed objects, but it stores the objects themselves"

So OwnedArray is an intrusive container and std::vector is non-intrusive.

I hope this helps explain further.


#4

Normally the [] operator returns a reference to the object so that it can be used on the left side of an assignment, for example:

 

foo[7] = 42;

 

If it returned a copy of the object this wouldn't work because you would only assign to the copy.

 

But OwnedArray operator[] returns a pointer, not a reference. I think you'd have to ask the designer why. One guess would be so that it could handle the case of an index out of range. For a std::vector, using an index out of range causes undefined behavior. But OwnedArray just returns a null pointer in that case. Of course then you have to check the pointer before using it.

 

BTW, I wouldn't consider OwnedArray as an intrusive container. Intrusive containers require that the items being stored be modified to handle the links between items. (So no need for intrusive arrays, true? I didn't see any Boost intrusive array.) As an non-intrusive container, OwnedArray stores copies of pointers. It technically doesn't store the objects, just pointers to them, even though it does delete them.

 

I suppose the main motivation for OwnedArray was to have an array that (1) managed the lifetime of the objects, and (2) didn't require a copy, which not only gives better performance but allows non-copyable objects and (3) did this without the benefit of rvalue references.


#5

I want to thank everyone for their informative posts (better late than never). Very appreciated. :+1: