0

Does an auto_ptr have the same size as a pointer?

I have to substitute it with a boost::scoped_ptr, and I was wondering if these two data types have the same size.

Pietro
  • 12,086
  • 26
  • 100
  • 193
  • 1
    The size is likely left to the implementer. – chris Mar 16 '15 at 17:15
  • 2
    Why don't you just do a print sizeof? PS. It would be more than a pointer because it needs a reference counter – SwiftMango Mar 16 '15 at 17:15
  • 3
    "and I was wondering if these two data types have the same size." – why do you need this information for changing it to `boost::scoped_ptr`? – The Paramagnetic Croissant Mar 16 '15 at 17:16
  • 8
    @texasbruce: Neither `auto_ptr` not `scoped_ptr` are reference-counted. `shared_ptr` is, but has to store the reference count in a separate shared data structure, not the pointer object itself. There's no need for any of them to contain more than a pointer. – Mike Seymour Mar 16 '15 at 17:18
  • 4
    @MikeSeymour `shared_ptr` actually usually contains two pointers - one to the referencing counting block, and one for the return value of `get()`, which can be completely unrelated to the object whose lifetime it manages. – T.C. Mar 16 '15 at 17:19
  • 7
    Why are we still talking about `auto_ptr`? `std::unique_ptr` is better, search and destroy `auto_ptr`. – Ben Voigt Mar 16 '15 at 17:26
  • @BenVoigt: Or `boost::scoped_ptr`, if C++11 isn't available. Just like the question says. – Mike Seymour Mar 16 '15 at 17:30
  • @MikeSeymour Yes I was referring to std::shared_ptr. Not sure how boost::auto_ptr is implemented. But if there is an underlying implementation struct, we still cannot say it is only one pointer size as big. – SwiftMango Mar 16 '15 at 17:34
  • @BenVoigt: I am talking about `auto_ptr` because I have to replace them with something else. And Mike just guessed why I cannot use `std::unique_ptr`. – Pietro Mar 16 '15 at 17:39
  • So is your real question "Will memory requirements increase if I switch from `std::auto_ptr` to `boost::scoped_ptr`?" or "Will switching from `std::auto_ptr` to `boost::scoped_ptr` affect CPU cache performance?". Because really the only valid case I can think of where the actual size being the same matters is if you are using a pooled allocator and want to know if structures which are equal except for the pointer type will use a common allocation size. – Ben Voigt Mar 16 '15 at 18:01
  • @Pietro: It's not really an answer. There's no need for any more than a pointer; but no guarantee that there won't be. Check `sizeof` if you want to know for sure. – Mike Seymour Mar 16 '15 at 18:33

1 Answers1

2

You can pretty easily find out what the sizes are by simply doing this:

#include <iostream>
#include <memory>

#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>

int main() {
  std::cout << "raw pointer: " << sizeof(int*) << std::endl;
  std::cout << "auto-ptr: " << sizeof(std::auto_ptr<int>) << std::endl;
  std::cout << "unique-ptr: " << sizeof(std::unique_ptr<int>) << std::endl;
  std::cout << "shared-ptr: " << sizeof(std::shared_ptr<int>) << std::endl;
  std::cout << "boost scoped-ptr: " << sizeof(boost::scoped_ptr<int>) << std::endl;
  std::cout << "boost shared-ptr: " << sizeof(boost::shared_ptr<int>) << std::endl;
  return 0;
};

On my platform (64bit), with GCC 4.8.2 and Boost 1.55, I get this output:

raw pointer: 8
auto-ptr: 8
unique-ptr: 8
shared-ptr: 16
boost scoped-ptr: 8
boost shared-ptr: 16

Of course, there is no strict guarantee that these results will be the same anywhere. In other words, the standard does not require that auto-ptr or unique-ptr (C++11) be of the same size as a regular (raw) pointer. As far as I can see, the Boost documentation does not explicitly give that guarantee either for scoped-ptr, but they do give the following statement:

Because scoped_ptr is simple, in its usual implementation every operation is as fast as for a built-in pointer and it has no more space overhead that a built-in pointer.

I would say that it is pretty safe to assume that the above statement holds true for any decent implementation of either auto-ptr, unique-ptr or scoped-ptr. If you test it on some platform and get a result that contracts that, then I would consider that implementation to be worthless unusable garbage. There is no sensible reason for either one of these smart pointers to contain anything more than a single pointer (except for unique-ptr which could have to make place for a non-empty custom deleter object, but otherwise, should have the same size as the other two).

And by the way, if you are also curious about why shared-ptr has a size of 16 in my tests. That's because the features of shared-ptr make it so that individual shared-pointers must contain 2 pointers: one is a (possibly aliasing) pointer to the object in question, and one is a pointer to the reference-counting shared data structure that all its associated shared- or weak- pointers use. The fact that shared-pointers can point to something other than what is actually being managed by the reference-counting (or some related but different pointer, like a pointer to a member or base- / derived- class) is the reason why it needs that local pointer in addition to the pointer to the reference-counting shared data (and also, it also performs better when the pointer to the object can be obtained directly, without having to go through the shared data structure). But this is still a reasonable overhead for when you need reference-counting.

Mikael Persson
  • 18,174
  • 6
  • 36
  • 52
  • Great answer. But no one has mentioned that `sizeof()` doesn't include any additional overhead. A typical implementation of `shared_ptr` allocates a pointer to the 'owned' object and a pointer to a "control block". That control block includes a strong reference count, a copy of the deleter and a weak reference count. The memory of `shared_ptr` is typically more than 2 pointers (being typically 16 bytes). None of these considerations apply to any plausible implementation of `auto_ptr`. – Persixty Mar 23 '15 at 12:52