2

A similar question has been asked here:

Class members that are objects - Pointers or not? C++

so I'll keep it brief.

Say I have an object that contains three stl vectors. Is my thinking correct that if they are regular members of the class, the memory of them will be "together" for the whole object? e.g. my memory would look sth like 10 blocks vector A, 5 blocks vector B, and then 15 blocks vector C. Would then once I insert more objects into vector A so that the space runs out the whole structure including vector B and C need to be moved?

Is that then an argument for pointers? Or are vectors internally only a pointer to the allocated memory? Same question would go for lists etc...

Are there any rules of thumb as to the cost of a redirection vs the cost of copying small objects? Maybe sth along the lines of 5 pointer redirection = 1 integer copy?

Thanks

Community
  • 1
  • 1
Cookie
  • 12,004
  • 13
  • 54
  • 83

3 Answers3

2

Say I have an object that contains three stl vectors. Is my thinking correct that if they are regular members of the class, the memory of them will be "together" for the whole object? e.g. my memory would look sth like 10 blocks vector A, 5 blocks vector B, and then 15 blocks vector C.

Each vector occupies a fixed size in the containing object, independent of the number of elements currently stored by the vector. It is likely that the value_type of the vector (e.g. vector<int> has value_type int) won't affect the size of the contained vector object itself: only the amount of heap-allocated store the vector needs in order to maintain its storage capacity (so they're likey to be say 8 or 16 or 32 bytes each but all the same, but not 10 "blocks" (whatever that might be), 5 blocks and 15).

Would then once I insert more objects into vector A so that the space runs out the whole structure including vector B and C need to be moved?

Inserting elements into A can only ever cause existing elements in A to be moved (when the capacity is exceeded). B and C can never be affected.

Is that then an argument for pointers? Or are vectors internally only a pointer to the allocated memory?

YES, it's an argument... such a good one that YES, vectors already do use pointers to the contiguous memory where the actual value_type elements are stored.

Same question would go for lists etc...

YES, lists store their value_type elements on the heap too, and the size of the object embedding or derived from list is unaffected by operations on the list.

Are there any rules of thumb as to the cost of a redirection vs the cost of copying small objects? Maybe sth along the lines of 5 pointer redirection = 1 integer copy?enter code here

C++ runs on too many platforms for there to be good rules of thumb for this. Even on say x86 processors, differences in instruction set, # cores, cache sizes, CPU vendor / model / generation etc. can be overwhelming. Indirection is most costly if it results in memory page faults, and that's very dependent on the overall picture of program execution on the machine. If you care, benchmark real computers running the program until you find statistically relevant and stable results.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
1

Collection classes are implemented internally using pointers - you don't have to worry about them running out of space. As for the copying overhead, don't worry about it unless you have proved by profiling your code that it is a problem.

0

Since std::vector are dynamically sized, they can't possibly stores their elements as members or as a member array. Remember that the size of an object is known at compile-time.

Even then, there is still something to be said about not using pointer members. Consider this type:

struct fat {
    array<double, 30> data;
    array<long, 30> more_data;
    array<char, 30> too_much_data;
};

where array can be std::array, std::tr1::array or boost::array; it's here just used as a stand-in for a large type. You are correct that fat objects will be, well, large. Changing the members to pointers (or dynamic arrays or any kind of moral equivalent) is still premature: first use the objects as-is, and then if it's too big or otherwise problematic you can dynamically allocate them instead of the members:

fat* so_much_stuff = new fat[30]();
// Better:
std::vector<fat> get_rid_of_it_already(30);

Value semantics just make things easier; it's only until it's too much copying or size or whatever (measure first) but not before that you should use (dynamic) containers and smart pointers (that themselves follow value semantics).

EDIT

std::vector is not 'bad' in general (as a member or not), see the discussion with Tony in the comments.

Luc Danton
  • 34,649
  • 6
  • 70
  • 114
  • 1
    Nice that you've been thinking about this and write well, but your reasoning is flawed by 2 oversights: 1) dynamic allocation using `vector<>` has the compelling benefit of resizing and continuing to run, whereas compile-time array sizing wastes memory when there are fewer elements, then fails totally. 2) `vector` *does* have value semantics (that C++ lets you create user-defined types with value semantics is a critical and very deliberate language feature), and `vector`s are therefore automatically handled properly by default-generated destructors and copy constructors. – Tony Delroy May 09 '11 at 16:13
  • @Tony You are correct, I am not advocating using `std::array` over `std::array`. I am advising against prematurely using `std::vector` over `std::array` *as a member* solely on the grounds that it would make a leaner object. Choosing between `std::array` or `std::vector` (as a member or not) is another discussion altogether, and you already provided some arguments on the subject. – Luc Danton May 09 '11 at 16:20
  • @Luc: if your "leaner object" caveat is warning that say a `vector` with size N will not be as "lean" as an array of size N that's certainly true, but vectors definitely come into their own when the populated size is significantly less than the capacity N, and in resizing beyond the current capacity on demand. `vector`s value semantics make them well-behaved members, and they should be selected in preference to arrays in general use. Using `array` habitually would be the "premature" choice, as it's normally hard to choose a good capacity. I'm still not sure if you're agreeing or not? :-) – Tony Delroy May 09 '11 at 16:42
  • @Tony No that's not it. We're also not agreeing or disagreeing because you're addressing (in your first comment) something that I'm not (in my answer). `array` was used for illustration purpose and because it appeared in the question; it can't be premature in my answer *because it's the premise*. – Luc Danton May 09 '11 at 16:49
  • @Luc: array's never mentioned in this question - only vector... :-/. ANyway, no worries... – Tony Delroy May 10 '11 at 00:58
  • @Tony The question mentioned the possibility that the size of `vector` be dependent on the numbers of elements, hence that it behaved like `array` does. – Luc Danton May 10 '11 at 01:43
  • @Luc: oh, fair enough... with you now. Cheers. – Tony Delroy May 10 '11 at 01:46