22

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?

13
  • 10
    I'll ask a question back: who shall own the objects you can access by index? The vector? Or will the vector point or reference to another actual owner? Commented Dec 24, 2018 at 18:07
  • 4
    Also, is Apple polymorphic? Commented Dec 24, 2018 at 18:08
  • 4
    HolyBlackCat: that's a good question, Apple is not polymorphic. But if it was, we'd definitely want to use a pointer, right? Commented Dec 24, 2018 at 18:09
  • 6
    @HolyBlackCat: I think so. They sell hardware and software. <g> Commented Dec 24, 2018 at 18:10
  • 2
    If it was polymorphic, I'd suggest figure out how to make a copyable unique_ptr wrapper (using type erasure) and use that. If it sounds too hard, use pointers. Commented Dec 24, 2018 at 18:11

2 Answers 2

22

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.

Sign up to request clarification or add additional context in comments.

Comments

11

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 Apples in it so that the lifetimes are sensibly managed.

3 Comments

Note that not all of them work. A vector of references is not allowed.
@Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
@Vassilis Jup, but a reference_wrapper is not a reference :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.