Should a std::vector of objects use pointers, references, or nothing?












14














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?










share|improve this question




















  • 7




    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?
    – Zeta
    17 hours ago








  • 3




    Also, is Apple polymorphic?
    – HolyBlackCat
    17 hours ago






  • 3




    HolyBlackCat: that's a good question, Apple is not polymorphic. But if it was, we'd definitely want to use a pointer, right?
    – helper
    17 hours ago






  • 6




    @HolyBlackCat: I think so. They sell hardware and software. <g>
    – Rudy Velthuis
    17 hours ago






  • 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.
    – HolyBlackCat
    17 hours ago


















14














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?










share|improve this question




















  • 7




    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?
    – Zeta
    17 hours ago








  • 3




    Also, is Apple polymorphic?
    – HolyBlackCat
    17 hours ago






  • 3




    HolyBlackCat: that's a good question, Apple is not polymorphic. But if it was, we'd definitely want to use a pointer, right?
    – helper
    17 hours ago






  • 6




    @HolyBlackCat: I think so. They sell hardware and software. <g>
    – Rudy Velthuis
    17 hours ago






  • 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.
    – HolyBlackCat
    17 hours ago
















14












14








14


1





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?










share|improve this question















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?







c++ stl






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 15 hours ago









Quark

112




112










asked 17 hours ago









helper

311112




311112








  • 7




    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?
    – Zeta
    17 hours ago








  • 3




    Also, is Apple polymorphic?
    – HolyBlackCat
    17 hours ago






  • 3




    HolyBlackCat: that's a good question, Apple is not polymorphic. But if it was, we'd definitely want to use a pointer, right?
    – helper
    17 hours ago






  • 6




    @HolyBlackCat: I think so. They sell hardware and software. <g>
    – Rudy Velthuis
    17 hours ago






  • 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.
    – HolyBlackCat
    17 hours ago
















  • 7




    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?
    – Zeta
    17 hours ago








  • 3




    Also, is Apple polymorphic?
    – HolyBlackCat
    17 hours ago






  • 3




    HolyBlackCat: that's a good question, Apple is not polymorphic. But if it was, we'd definitely want to use a pointer, right?
    – helper
    17 hours ago






  • 6




    @HolyBlackCat: I think so. They sell hardware and software. <g>
    – Rudy Velthuis
    17 hours ago






  • 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.
    – HolyBlackCat
    17 hours ago










7




7




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?
– Zeta
17 hours ago






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?
– Zeta
17 hours ago






3




3




Also, is Apple polymorphic?
– HolyBlackCat
17 hours ago




Also, is Apple polymorphic?
– HolyBlackCat
17 hours ago




3




3




HolyBlackCat: that's a good question, Apple is not polymorphic. But if it was, we'd definitely want to use a pointer, right?
– helper
17 hours ago




HolyBlackCat: that's a good question, Apple is not polymorphic. But if it was, we'd definitely want to use a pointer, right?
– helper
17 hours ago




6




6




@HolyBlackCat: I think so. They sell hardware and software. <g>
– Rudy Velthuis
17 hours ago




@HolyBlackCat: I think so. They sell hardware and software. <g>
– Rudy Velthuis
17 hours ago




2




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.
– HolyBlackCat
17 hours ago






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.
– HolyBlackCat
17 hours ago














2 Answers
2






active

oldest

votes


















15














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.






share|improve this answer































    10














    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.






    share|improve this answer

















    • 4




      Note that not all of them work. A vector of references is not allowed.
      – Rakete1111
      14 hours ago






    • 2




      @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
      – Vassilis
      12 hours ago








    • 4




      @Vassilis Jup, but a reference_wrapper is not a reference :)
      – Rakete1111
      12 hours ago













    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53916524%2fshould-a-stdvector-of-objects-use-pointers-references-or-nothing%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    15














    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.






    share|improve this answer




























      15














      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.






      share|improve this answer


























        15












        15








        15






        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.






        share|improve this answer














        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.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        answered 17 hours ago


























        community wiki





        Zeta


























            10














            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.






            share|improve this answer

















            • 4




              Note that not all of them work. A vector of references is not allowed.
              – Rakete1111
              14 hours ago






            • 2




              @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
              – Vassilis
              12 hours ago








            • 4




              @Vassilis Jup, but a reference_wrapper is not a reference :)
              – Rakete1111
              12 hours ago


















            10














            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.






            share|improve this answer

















            • 4




              Note that not all of them work. A vector of references is not allowed.
              – Rakete1111
              14 hours ago






            • 2




              @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
              – Vassilis
              12 hours ago








            • 4




              @Vassilis Jup, but a reference_wrapper is not a reference :)
              – Rakete1111
              12 hours ago
















            10












            10








            10






            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.






            share|improve this answer












            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.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 17 hours ago









            David Schwartz

            135k14140223




            135k14140223








            • 4




              Note that not all of them work. A vector of references is not allowed.
              – Rakete1111
              14 hours ago






            • 2




              @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
              – Vassilis
              12 hours ago








            • 4




              @Vassilis Jup, but a reference_wrapper is not a reference :)
              – Rakete1111
              12 hours ago
















            • 4




              Note that not all of them work. A vector of references is not allowed.
              – Rakete1111
              14 hours ago






            • 2




              @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
              – Vassilis
              12 hours ago








            • 4




              @Vassilis Jup, but a reference_wrapper is not a reference :)
              – Rakete1111
              12 hours ago










            4




            4




            Note that not all of them work. A vector of references is not allowed.
            – Rakete1111
            14 hours ago




            Note that not all of them work. A vector of references is not allowed.
            – Rakete1111
            14 hours ago




            2




            2




            @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
            – Vassilis
            12 hours ago






            @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
            – Vassilis
            12 hours ago






            4




            4




            @Vassilis Jup, but a reference_wrapper is not a reference :)
            – Rakete1111
            12 hours ago






            @Vassilis Jup, but a reference_wrapper is not a reference :)
            – Rakete1111
            12 hours ago




















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53916524%2fshould-a-stdvector-of-objects-use-pointers-references-or-nothing%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Human spaceflight

            Can not write log (Is /dev/pts mounted?) - openpty in Ubuntu-on-Windows?

            張江高科駅