Thread: When c++ returns, is it the same as a copy?

  1. #1
    Registered User
    Join Date
    Aug 2005
    Posts
    266

    When c++ returns, is it the same as a copy?

    If I return a gigantic vector of integers from a function, am I better off just passing a reference to the function instead and having it filled that way? I'm wondering if returning a vector that takes up a very large amount of memory is a problem.

    for example:

    Code:
    vector<int> getPrimes()
    {
    vector<int> primes;
    //FILL vector<int> with a bajillion integers
    return primes;
    }
    
    void getPrimes(vector<int>& primes)
    {
    //FILL vector<int> with a bajillion integers
    }
    Is there any difference whatsoever? (besides programming style)

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    There is a difference, but it also depends on your compiler.
    Generally speaking, a copy will be made when you return the vector (that means all its contents will be copied).
    However, it is also true that the compiler is allowed to make an optimization to avoid that copying, which essentially means that the compiler converts the code into the second variant.

    So either you should not rely on it, or you should test if your specific compiler supports this optimization, by say, timing the time it takes to run the code in a loop of of n iterations.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    C++ Junkie Mozza314's Avatar
    Join Date
    Jan 2011
    Location
    Australia
    Posts
    174
    Quick tip: unless you know how many primes you're going to generate, (as opposed to say, a function that generates all primes below N), consider using a deque instead of a vector. A vector starts out with a certain amount of memory available and if you try to put more elements than it can fit into this memory it finds a new, bigger block of memory and copies the whole thing into the new memory, which is exactly what you've expressed desire to avoid. Of course if you know how much memory you're going to need at the beginning, or a have a decent upper bound on how much memory you'll need, you can get around this using vector::reserve(). A deque is more clever with its memory management and can offer virtually all the features of vector without much extra overhead.

  4. #4
    Registered User
    Join Date
    Aug 2010
    Location
    Poland
    Posts
    733
    As Mozza314 said, you should consider deque. Actually std::string is the only container (well, theoretically it is not a container) that I return. I just don't meet many situation where I need to return a vector, so if I do, I pass it as a reference, because:

    1. I will never forget about using this vector. If I attempt not to use the returned vector, I will rethink my design.
    2. Mentioned (lack of) compiler optimizations.
    3. It's pretty comfortable to operate on the destination vector, no need to create local one.

    EDIT:
    I forgot, I used to return vector in several functions of my project, but always as a shared pointer.

    The annoying part of deque is that it is a little bit slower (I mean random access, since you need to acquire chunk first) and you have no idea how big chunks are.
    Last edited by kmdv; 02-20-2011 at 05:14 AM.

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You really should stick with a vector unless you believe you need another type of container. If it turns out a vector is slow, then you should consider alternatives.
    That is, don't jump to conclusions that a deque will always be better.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Then again, it's always good to know your containers.

    Therefore they provide a similar functionality as the one provided by vectors, but with efficient insertion and deletion of elements also at the beginning of the sequence and not only at its end. On the drawback side, unlike vectors, deques are not guaranteed to have all its elements in contiguous storage locations, eliminating thus the possibility of safe access through pointer arithmetics.

    Both vectors and deques provide thus a very similar interface and can be used for similar purposes, but internally both work in quite different ways: While vectors are very similar to a plain array that grows by reallocating all of its elements in a unique block when its capacity is exhausted, the elements of a deques can be divided in several chunks of storage, with the class keeping all this information and providing a uniform access to the elements. Therefore, deques are a little more complex internally, but this generally allows them to grow more efficiently than the vectors with their capacity managed automatically, specially in large sequences, because massive reallocations are avoided.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It is. But it's also a question of: are you always going to sacrifice random or linear iteration speed for the sake of a little gain in copying?
    Therefore, it is usually best, unless you know you have specific needs, to simply use the default vector, and switch if it presents a problem.
    Or you can try both, and time them, to see which one performs better in your program.
    Remember that premature optimization is the root of much evil.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    But it's also a question of: are you always going to sacrifice random or linear iteration speed for the sake of a little gain in copying?
    Your question is addressed by the quoted, and elaborated on, in the documentation I linked. FYI, deque does provide random access to elements and gets the same time complexity as vector on many operations including insertion and deletion. The difference between the two is very clearly stated in this thread and in other places. People's posts have made the information necessary. Make me a martyr for being helpful.

    As for "a little gain in copying" well copying around is the only way reallocation works for contiguous memory. Unless you need contiguous memory (because you're doing pointer arithmetic?) it's an important optimization. Do I care what the OP does? Not really.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by whiteflags View Post
    Your question is addressed by the quoted, and elaborated on, in the documentation I linked. FYI, deque does provide random access to elements and gets the same time complexity as vector on many operations including insertion and deletion. The difference between the two is very clearly stated in this thread and in other places. People's posts have made the information necessary. Make me a martyr for being helpful.
    My point being that even though they are O(1), the constant time differs. Vector may be O(a) and deque O(b) where a, b are constants and a != b.
    It is clearly stated in the documentation that random access is a little slower with deque.
    That why I am simply stating "don't blindly jump into a container because you think it might be better." First, make a good argument that it is better. Secondly, prove that it is better.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    It is clearly stated in the documentation that random access is a little slower with deque.
    I am sure that this will matter while you wait for vector to reallocate itself in the midst of calculating a "bajillion" primes to list.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yes, it probably will, if it turns out you use it that way. But if you're not, and using a lot of random access, you will probably have to wait for the deque to churn all the time.
    Just be aware of what you're doing. Don't blindly jump to a container.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    C++ Junkie Mozza314's Avatar
    Join Date
    Jan 2011
    Location
    Australia
    Posts
    174
    I'd be really interested to see someone replicate similar results, but I think a really good article on this is:

    An In-Depth Study of the STL Deque Container - CodeProject

    It actually seems the biggest drawback of a deque is the time to reclaim the memory; the difference between element access is very small (~1.7%).
    Last edited by Mozza314; 02-20-2011 at 03:14 PM. Reason: typo

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    My biggest gripe from a quick overview with the article is that it doesn't mention what implementation it was tested on.
    OK, having read the entire article, three things gripe me:
    - There was no mention on what implementation the tests were made.
    - There was no mention if it was done multiple implementations, and if so, which ones it were. That probably concludes it was done on only one.
    - No source code was analyzed.
    In other words, the article cannot be trusted. The statistics are useless. We cannot draw any conclusions from it.
    Last edited by Elysia; 02-20-2011 at 03:33 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    - There was no mention if it was done multiple implementations, and if so, which ones it were. That probably concludes it was done on only one.
    The standard libraries have the same theoretical performance requirements, which can be exceeded (maybe) but AFAIK they aren't. Even if say the GNU implementation did some things faster by X amount, why would you draw a different conclusion about vector versus deque on the whole? Who wants to design software on the basis of "Oh I can use my favorite container with this implementation of the STL"?

    - No source code was analyzed.
    To what end would you want to do this and why?

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by whiteflags View Post
    The standard libraries have the same theoretical performance requirements, which can be exceeded (maybe) but AFAIK they aren't.
    It still doesn't rule out the question that some standard libraries may be poorly optimized. One of the comments mention that sorting a vector vs a deque ended in vector's facor with a 2.8x or so factor. This is a most curious result.
    This covers the part that they must have the same theoretical performance requirements. I simply don't trust an implementation to conform to that when it comes to tests.

    Even if say the GNU implementation did some things faster by X amount, why would you draw a different conclusion about vector versus deque on the whole?
    No.

    Who wants to design software on the basis of "Oh I can use my favorite container with this implementation of the STL"?
    Certainly not I. That is why I would have liked to see this done on multiple implementations at the very least.
    We also have to factor in the possibility of different compilers and how good they are at optimizing things.

    To what end would you want to do this and why?
    To make sure the implementation is good and not some poor rip-off implementation.
    The possibility that there are very poor implementations out there is not so farfetched.
    And also give proof or backing to claimed test results.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Gcc can't find obvious copy constructor
    By SevenThunders in forum C++ Programming
    Replies: 13
    Last Post: 03-19-2009, 02:41 PM
  2. How to copy a C struct to a C++ class?
    By Ptbamboo in forum C++ Programming
    Replies: 1
    Last Post: 02-21-2009, 02:11 PM
  3. Polynomials and ADT's
    By Emeighty in forum C++ Programming
    Replies: 20
    Last Post: 08-19-2008, 08:32 AM
  4. Copying constant amount of data
    By TriKri in forum C++ Programming
    Replies: 16
    Last Post: 07-12-2008, 06:32 AM
  5. Copy constructor question
    By BigFish21 in forum C++ Programming
    Replies: 9
    Last Post: 05-04-2008, 12:18 PM