Suppose we have some class, say class Apple
, and wanted to store a std::vector
containing Apple
.
Should the vector contain pointers, references, or plain objects?
std::vector<Apple*> vector; // Definitely won't copy the Apple on lookup, // but I would prefer not to use pointers if I don't have to std::vector<Apple&> vector; // Seems circuitous? std::vector<Apple> vector; // I don't know if this copies the Apple on each lookup
My goal is to make it so when I call
Apple& a = vector[4];
the Apple
won't get copied.
I've been using C++ for over a year and I've always worked around this and never understood it. Is there a simple explanation of why one of these three approaches is the best practice?
Use references when you can, and pointers when you have to. References are usually preferred over pointers whenever you don't need “reseating”. This usually means that references are most useful in a class's public interface. References typically appear on the skin of an object, and pointers on the inside.
An alternative method uses a pointer to access the vector. w = new std::vector<int>(); The new operator creates a new, empty vector of ints and returns a pointer to that vector. We assign that pointer to the pointer variable w , and use w for the remainder of the code to access the vector we created with new .
std::vector::dataReturns a direct pointer to the memory array used internally by the vector to store its owned elements.
Yes. std::vector and std::string are automatically when they finish out of scope, calling also the destructor of the objects contained (for std::vector ). As said before, std::vector is destroyed when it finish out of scope, calling the destructor of the objects contained.
Use the type T
. Remember that operator[]
returns a (const) reference, so your Apple&
works fine there:
T& vector<T>::operator[](size_t); const T& vector<T>::operator[](size_t) const;
That's why you can use vec[3].make_older()
to begin with if return_type Apple::make_older(void)
exists.
However, keep in mind that there are many methods that invalidate references, so
Apple& reference = vec[3]; vec.push_back(other_apple); reference.get_eaten();
might result in undefined behaviour if push_back
reallocated the referenced apple.
Use:
std::vector<Apple> vector; // I don't know if this copies the Apple on each lookup
While all of them would achieve your goal (a lookup never copies), this is the one that allows the vector
to own the Apple
s in it so that the lifetimes are sensibly managed.
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