vector.push_back - pushes values or references?

Discussion in 'C++' started by Siam, Feb 17, 2007.

  1. Siam

    Siam Guest

    Hi,

    I'm a little new to stl so bear with me...Say I have the following
    code:

    vector<int> vec;
    int i = 3;
    vec.push_back(i);
    i=4;
    cout<<vec.at(0)<<endl;

    Looking at the signature of push_back, it seems to take a reference:

    void push_back( const TYPE& val );

    I wouldve thought that means the int i pass to the vector isn't
    copied, but a reference to the original int is placed in the vector.
    However, the above code returns 3, not 4, indicating the int has been
    copied into the vector (on printing memory addresses, the ints are
    stored in different memory addresses). My question is, why does the
    push_back function take a reference, but yet still store a copy of the
    object in the vector?

    Cheers,

    SR
     
    Siam, Feb 17, 2007
    #1
    1. Advertising

  2. Siam

    Jim Langston Guest

    "Siam" <> wrote in message
    news:...
    > Hi,
    >
    > I'm a little new to stl so bear with me...Say I have the following
    > code:
    >
    > vector<int> vec;
    > int i = 3;
    > vec.push_back(i);
    > i=4;
    > cout<<vec.at(0)<<endl;
    >
    > Looking at the signature of push_back, it seems to take a reference:
    >
    > void push_back( const TYPE& val );
    >
    > I wouldve thought that means the int i pass to the vector isn't
    > copied, but a reference to the original int is placed in the vector.
    > However, the above code returns 3, not 4, indicating the int has been
    > copied into the vector (on printing memory addresses, the ints are
    > stored in different memory addresses). My question is, why does the
    > push_back function take a reference, but yet still store a copy of the
    > object in the vector?
    >
    > Cheers,
    >
    > SR


    ..push_back() eventually uses the copy constructor of the object. So most
    likly it accepts a reference, then calls the copy constructor on the
    reference it has. Easy to determine this, just make a class with a private
    copy constructor and try to make a vector out of it and use .push_back()
     
    Jim Langston, Feb 17, 2007
    #2
    1. Advertising

  3. Siam

    Ian Collins Guest

    Siam wrote:
    > Hi,
    >
    > I'm a little new to stl so bear with me...Say I have the following
    > code:
    >
    > vector<int> vec;
    > int i = 3;
    > vec.push_back(i);
    > i=4;
    > cout<<vec.at(0)<<endl;
    >
    > Looking at the signature of push_back, it seems to take a reference:
    >
    > void push_back( const TYPE& val );
    >
    > I wouldve thought that means the int i pass to the vector isn't
    > copied, but a reference to the original int is placed in the vector.
    > However, the above code returns 3, not 4, indicating the int has been
    > copied into the vector (on printing memory addresses, the ints are
    > stored in different memory addresses). My question is, why does the
    > push_back function take a reference, but yet still store a copy of the
    > object in the vector?
    >

    Passing by reference insures only one copy of the object is made. If
    the function used pass by value, the object would be copied twice.

    --
    Ian Collins.
     
    Ian Collins, Feb 17, 2007
    #3
  4. Siam

    Ian Collins Guest

    Ian Collins wrote:
    > Siam wrote:
    >
    >>Hi,
    >>
    >>I'm a little new to stl so bear with me...Say I have the following
    >>code:
    >>
    >>vector<int> vec;
    >>int i = 3;
    >>vec.push_back(i);
    >>i=4;
    >>cout<<vec.at(0)<<endl;
    >>
    >>Looking at the signature of push_back, it seems to take a reference:
    >>
    >>void push_back( const TYPE& val );
    >>
    >>I wouldve thought that means the int i pass to the vector isn't
    >>copied, but a reference to the original int is placed in the vector.
    >>However, the above code returns 3, not 4, indicating the int has been
    >>copied into the vector (on printing memory addresses, the ints are
    >>stored in different memory addresses). My question is, why does the
    >>push_back function take a reference, but yet still store a copy of the
    >>object in the vector?
    >>

    >
    > Passing by reference insures only one copy of the object is made. If
    > the function used pass by value, the object would be copied twice.
    >

    Oops, s/insures/ensures/ :)

    --
    Ian Collins.
     
    Ian Collins, Feb 17, 2007
    #4
  5. * Siam:
    > Hi,
    >
    > I'm a little new to stl so bear with me...Say I have the following
    > code:
    >
    > vector<int> vec;
    > int i = 3;
    > vec.push_back(i);
    > i=4;
    > cout<<vec.at(0)<<endl;
    >
    > Looking at the signature of push_back, it seems to take a reference:
    >
    > void push_back( const TYPE& val );
    >
    > I wouldve thought that means the int i pass to the vector isn't
    > copied, but a reference to the original int is placed in the vector.
    > However, the above code returns 3, not 4, indicating the int has been
    > copied into the vector (on printing memory addresses, the ints are
    > stored in different memory addresses). My question is, why does the
    > push_back function take a reference, but yet still store a copy of the
    > object in the vector?


    Because std::vector can be used for any copyable type, and for some
    types an object may have a lot of data to be copied, and/or copying the
    object may involve dynamic allocation, which is (relatively) slow.

    The reference passing means that an object that is expensive to copy is
    only copied once, namely when copied into the vector's storage.

    It's not copied in the process of being passed as argument, because with
    a reference argument and a resonable compiler all that's passed (if
    anything is passed!) is the object's memory address.

    Using 'T const&' (or equivalently 'const T&') is a very common idiom for
    objects that may be expensive to copy.

    E.g., instead of writing a formal argument as 'std::string s', you
    should as a matter of course write 'std::string const& s', even if
    std::string might be expected to be heavily optimized and perhaps
    directly supported by the compiler.

    Caveat: don't do that for function results, e.g. don't declare a
    function as 'std::string const& foo()' instead of 'std::string foo()'.

    Because that might result in a dangling reference (the referred to
    object doesn't exist after the function call has returned) and thus most
    probably Undefined Behavior where undesirable things may happen.

    Hope this helps,

    - Alf


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Feb 17, 2007
    #5
  6. Siam

    Siam Guest

    Ah great, thanks all :)

    SR
     
    Siam, Feb 17, 2007
    #6
  7. Siam

    Pete Becker Guest

    Siam wrote:
    >
    > void push_back( const TYPE& val );
    >


    Maybe, but that's not required by the language definition. These things
    are specified in a different way. The requirement is that
    vec.push_back(object) puts a copy of object into vec. Passing by value
    is okay, as is passing by const reference.

    > I wouldve thought that means the int i pass to the vector isn't
    > copied, but a reference to the original int is placed in the vector.
    > However, the above code returns 3, not 4, indicating the int has been
    > copied into the vector (on printing memory addresses, the ints are
    > stored in different memory addresses). My question is, why does the
    > push_back function take a reference, but yet still store a copy of the
    > object in the vector?
    >


    The reason for storing by value is that that's what the specification
    says. <g> The design of STL assumes that objects are cheap to create and
    to copy, so STL algorithms and containers deal with values, not
    references. If you need reference semantics, use TR1's reference_wrapper
    (also available from Boost), or use vector<TYPE*>. In both cases you
    have to ensure that your objects hang around at least as long as the
    container does. (For more details on reference_wrapper, see chapter 8 of
    my book, "The Standard C++ Library Extension"; for details on TR1's
    shared_ptr, see chapter 2).

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
     
    Pete Becker, Feb 17, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ganesh Gella
    Replies:
    5
    Views:
    1,224
    John Harrison
    Jul 14, 2003
  2. Hitesh Bhatiya
    Replies:
    4
    Views:
    4,547
    John Harrison
    Aug 13, 2003
  3. Kenneth Lantrip

    Pushes and Pops to/from stack?

    Kenneth Lantrip, Jul 30, 2004, in forum: C Programming
    Replies:
    14
    Views:
    781
    Michael Wojcik
    Aug 10, 2004
  4. Steve Kobes

    scanf pushes back two chars?

    Steve Kobes, Sep 6, 2004, in forum: C Programming
    Replies:
    7
    Views:
    430
    Keith Thompson
    Sep 6, 2004
  5. Replies:
    8
    Views:
    1,961
    Csaba
    Feb 18, 2006
Loading...

Share This Page