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












20














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




















  • 9




    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
    Dec 24 '18 at 18:07








  • 4




    Also, is Apple polymorphic?
    – HolyBlackCat
    Dec 24 '18 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?
    – helper
    Dec 24 '18 at 18:09






  • 6




    @HolyBlackCat: I think so. They sell hardware and software. <g>
    – Rudy Velthuis
    Dec 24 '18 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.
    – HolyBlackCat
    Dec 24 '18 at 18:11


















20














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




















  • 9




    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
    Dec 24 '18 at 18:07








  • 4




    Also, is Apple polymorphic?
    – HolyBlackCat
    Dec 24 '18 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?
    – helper
    Dec 24 '18 at 18:09






  • 6




    @HolyBlackCat: I think so. They sell hardware and software. <g>
    – Rudy Velthuis
    Dec 24 '18 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.
    – HolyBlackCat
    Dec 24 '18 at 18:11
















20












20








20


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 Dec 24 '18 at 20:09







user10823628

















asked Dec 24 '18 at 18:05









helperhelper

341112




341112








  • 9




    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
    Dec 24 '18 at 18:07








  • 4




    Also, is Apple polymorphic?
    – HolyBlackCat
    Dec 24 '18 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?
    – helper
    Dec 24 '18 at 18:09






  • 6




    @HolyBlackCat: I think so. They sell hardware and software. <g>
    – Rudy Velthuis
    Dec 24 '18 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.
    – HolyBlackCat
    Dec 24 '18 at 18:11
















  • 9




    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
    Dec 24 '18 at 18:07








  • 4




    Also, is Apple polymorphic?
    – HolyBlackCat
    Dec 24 '18 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?
    – helper
    Dec 24 '18 at 18:09






  • 6




    @HolyBlackCat: I think so. They sell hardware and software. <g>
    – Rudy Velthuis
    Dec 24 '18 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.
    – HolyBlackCat
    Dec 24 '18 at 18:11










9




9




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
Dec 24 '18 at 18:07






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
Dec 24 '18 at 18:07






4




4




Also, is Apple polymorphic?
– HolyBlackCat
Dec 24 '18 at 18:08




Also, is Apple polymorphic?
– HolyBlackCat
Dec 24 '18 at 18:08




4




4




HolyBlackCat: that's a good question, Apple is not polymorphic. But if it was, we'd definitely want to use a pointer, right?
– helper
Dec 24 '18 at 18:09




HolyBlackCat: that's a good question, Apple is not polymorphic. But if it was, we'd definitely want to use a pointer, right?
– helper
Dec 24 '18 at 18:09




6




6




@HolyBlackCat: I think so. They sell hardware and software. <g>
– Rudy Velthuis
Dec 24 '18 at 18:10




@HolyBlackCat: I think so. They sell hardware and software. <g>
– Rudy Velthuis
Dec 24 '18 at 18:10




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
Dec 24 '18 at 18:11






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
Dec 24 '18 at 18:11














2 Answers
2






active

oldest

votes


















19














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

















    • 6




      Note that not all of them work. A vector of references is not allowed.
      – Rakete1111
      Dec 24 '18 at 20:35






    • 3




      @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
      – Vassilis
      Dec 24 '18 at 23:03








    • 6




      @Vassilis Jup, but a reference_wrapper is not a reference :)
      – Rakete1111
      Dec 24 '18 at 23:09













    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









    19














    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




























      19














      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


























        19












        19








        19






        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 Dec 24 '18 at 18:11


























        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

















            • 6




              Note that not all of them work. A vector of references is not allowed.
              – Rakete1111
              Dec 24 '18 at 20:35






            • 3




              @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
              – Vassilis
              Dec 24 '18 at 23:03








            • 6




              @Vassilis Jup, but a reference_wrapper is not a reference :)
              – Rakete1111
              Dec 24 '18 at 23:09


















            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

















            • 6




              Note that not all of them work. A vector of references is not allowed.
              – Rakete1111
              Dec 24 '18 at 20:35






            • 3




              @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
              – Vassilis
              Dec 24 '18 at 23:03








            • 6




              @Vassilis Jup, but a reference_wrapper is not a reference :)
              – Rakete1111
              Dec 24 '18 at 23:09
















            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 Dec 24 '18 at 18:11









            David SchwartzDavid Schwartz

            136k14142223




            136k14142223








            • 6




              Note that not all of them work. A vector of references is not allowed.
              – Rakete1111
              Dec 24 '18 at 20:35






            • 3




              @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
              – Vassilis
              Dec 24 '18 at 23:03








            • 6




              @Vassilis Jup, but a reference_wrapper is not a reference :)
              – Rakete1111
              Dec 24 '18 at 23:09
















            • 6




              Note that not all of them work. A vector of references is not allowed.
              – Rakete1111
              Dec 24 '18 at 20:35






            • 3




              @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
              – Vassilis
              Dec 24 '18 at 23:03








            • 6




              @Vassilis Jup, but a reference_wrapper is not a reference :)
              – Rakete1111
              Dec 24 '18 at 23:09










            6




            6




            Note that not all of them work. A vector of references is not allowed.
            – Rakete1111
            Dec 24 '18 at 20:35




            Note that not all of them work. A vector of references is not allowed.
            – Rakete1111
            Dec 24 '18 at 20:35




            3




            3




            @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
            – Vassilis
            Dec 24 '18 at 23:03






            @Rakete1111, A vector of references is not allowed but a vector of reference_wrapper does work.
            – Vassilis
            Dec 24 '18 at 23:03






            6




            6




            @Vassilis Jup, but a reference_wrapper is not a reference :)
            – Rakete1111
            Dec 24 '18 at 23:09






            @Vassilis Jup, but a reference_wrapper is not a reference :)
            – Rakete1111
            Dec 24 '18 at 23:09




















            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

            How do I know what Microsoft account the skydrive app is syncing to?

            When does type information flow backwards in C++?

            Grease: Live!