5

I am trying to find the difference in size from a struct with vector of object and struct with a vector of object pointers.

The code I have written shows that size of the both structs are the same even in theory at least based their content they should be different.

What would be the correct way of finding the correct size of a struct based on it's contents?

#include <iostream>
#include <string>
#include <vector>
using namespace std;

struct Song{
    string Name;
    string Artist;
};

struct Folder{
    vector<Song*> list;
};

struct Library{
    vector<Song> songs;
};

int main(int argc, const char * argv[]) {

    Library library;
    Folder favorites;
    Folder recentPurchaces;

    library.songs.push_back(Song{"Human After All", "Daft Punk"});
    library.songs.push_back(Song{"All of my love", "Led Zepplin"});


    favorites.list.push_back(&library.songs[0]);
    favorites.list.push_back(&library.songs[2]);


    cout << "Size of library: " << sizeof(library) << endl;
    cout << "Size of favorites: " << sizeof(favorites) << endl;



    return 0;
}
3
  • What's your expected and actual output? Commented Sep 18, 2014 at 19:13
  • My expected output is that library would be larger than favorites but they both show that they're 24 bytes Commented Sep 18, 2014 at 19:14
  • The size of a std::vector<> instance will stay the same, no matter what's stored there. All of the contained data goes to the heap. Commented Sep 18, 2014 at 19:15

3 Answers 3

4

in theory at least based their content they should be different.

No, the sizes shouldn't be different: std::vector<T> stores the data in dynamically allocated storage, while the struct stores only the "anchor" part, consisting of a couple of pointers. The number of items inside the vectors, as well as the size of the items inside the vector itself, are not counted in determining the size of this footprint.

In order to compute the size in memory you need to write a function that adds up sizes of the individual items inside each container, and add the capacity of a container itself, times the size of a container item.

Sign up to request clarification or add additional context in comments.

8 Comments

so something like sizeof(object) + object.list.size() * sizeof(stored list type)?
@user1721803 depending on your needs, you may need vector::capacity() instead of vector::size()
@user1721803 Yes, except you need to use capacity() instead of size(), because capacity is always greater than of equal to the size. Note, however, that this would not count the size of string's content, because strings are similar to vectors in that they may allocate content outside the string. It's a lot trickier, though, because strings may be optimized to store short content within the string itself. (Edit: Apparently, not after C++11 standard).
@dasblinkenlight I believe the C++11 rules for iterator invalidation and move semantics prevent short string optimisation.
@Angew The clause 23 containers (like std::vector) aren't allowed to use a small-container-optimization because their swaps are not allowed to invalidate iterators. basic_string's swap is allowed to invalidate iterators, permitting SSO. Its non-const operator [], begin(), end(), etc., aren't, preventing copy-on-write. This is actually noted in §C.2.12 [diff.cpp03.strings] - the situation is reversed in C++03, COW was allowed, SSO was prohibited.
|
3

Most likely, std::vector just keeps a pointer to a dynamically allocated array of elements, and the size of that pointer is the same regardless of whether it's Song* or Song**. The allocated size of the pointed-to memory would, of course, likely be different.

Put another way, sizeof() is not a good way to measure how much memory a std::vector requires.

Comments

2

Why would you expect the size of the structures to be different? std::vector stores its data via dynamic allocation ("on the heap"), so there is no reason for its implementation to contain anything else than a few pointers.

Exact implementation details depend on the standard library implementation, of course, but a typical std::vector<T, Alloc> could just contain something like this:

template <class T, class Alloc = allocator<T>>
class vector
{
  T *_Begin, *_End, *_EndOfCapacity;
  Alloc _Allocator;
  // No other data members

public:
  /* ... */
};

2 Comments

I want to find the total size of that struct object. How much total memory that object is taking up in memory whether it be on the stack or the heap
@user1721803 Then clarify your question accordingly. sizeof only gives size of the object itself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.