简体   繁体   中英

Difference in memory layout of vector of pairs and vector of structs containing two elements - C++/STL

Is the layout in memory of test1 and test2 the same?

std::vector<std::pair<int,int> > test1;
std::vector<mystruct>       test2;

where mystruct is defined as:

struct mystruct{
  int a;
  int b;
 };

Logically, std::pair<int, int> should be defined like that also.

There is however nothing about that on the standard and it is completely unguaranteed. You could take a look at the header files in your compiler to confirm that, but that doesn't prove anything.

Note: If you think it is absurd to be otherwise, I can give you an example how it could be defined otherwise. Imagine in the other stl template classes that use std::pair , they feel it would be convenient (for any reason), to have a pointer to the node containing the pair, in the pair. This way, they could, internally, add a pointer to the pair class while not violating any rules. Your assumption would then cause havoc. I would say it is unlikely for them to do such a thing, yes, but as long as they are not forced to that layout, anything can happen.

If you see on the cplusplus.com, you'll see that this is the struct of a pair:

template <class T1, class T2> struct pair
{
  typedef T1 first_type;
  typedef T2 second_type;

  T1 first;
  T2 second;
  pair() : first(T1()), second(T2()) {}
  pair(const T1& x, const T2& y) : first(x), second(y) {}
  template <class U, class V>
    pair (const pair<U,V> &p) : first(p.first), second(p.second) { }
}

Exactly the same, i would say, except some facts: Well, beginning with the fact that pairs are compatible with the std containers and all that, for example, maps. Also, the pairs are already made, and already have constructors for you.

EDIT: I also forgot to mention that you'll have std::make_pair for you, that allow you skipping allocating memory and making your own pair in a struct and you too have some comparison and assignment operators defined.

Yes, at least in Release mode it'll be the same size.

You shouldn't use this knowledge to do some memory trickery though, because of two reasons:

1) The std uses a lot of additional debugging stuff. That makes sizes of classes differ in debug and release mode. So it might very well be that std::pair is larger in debug mode.

2) The std might change internally. There is no guarantee that std::pair won't change it's memory layout in a different std version. So if you rely on that you have to live with the fear that one day it might not work anymore.

In any reasonable implementation of std::pair they will have the same layout. But this begs the question of why does it matter? You should not be doing a binary assignment from one to the other.

You can add a copy constructor to the struct, either directly or by subclassing it. You can also add a method that does the conversion the other way around.

struct mystruct{
  int a;
  int b;

  mystruct(const std::pair<int,int> &rhs) { a=rhs.first; b=rhs.second; }
  std::pair<int,int> as_pair() { return std::make_pair(a, b); }
 };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM