By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,873 Members | 1,040 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,873 IT Pros & Developers. It's quick & easy.

could/should allocator<T> be a static member?

P: n/a
Hi all,

I saw this code in the book "Accelerated C++" (chapt 11, iirc):

template <class T> class Vec {
...
std::allocator<T> alloc; // object to handle memory allocation

// ??would static member work here??:
// static std::allocator<T> alloc;
...
};

If i understand this correctly, in the code above,
every instance of Vec<T> gets its own allocator.

Wouldn't it be better "style" if alloc was a _static_ member?
Then all instances of Vec<T> would share one common allocator.
Is a static allocator guaranteed to work?

Thanks for comments/insights,
Bernhard Kick.
Jul 22 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
"Bernhard Kick" <be***********@gmx.de> wrote in message
news:f2**************************@posting.google.c om...
I saw this code in the book "Accelerated C++" (chapt 11, iirc):

template <class T> class Vec {
...
std::allocator<T> alloc; // object to handle memory allocation

// ??would static member work here??:
// static std::allocator<T> alloc;
...
};

If i understand this correctly, in the code above,
every instance of Vec<T> gets its own allocator.

Wouldn't it be better "style" if alloc was a _static_ member?
Then all instances of Vec<T> would share one common allocator.
Is a static allocator guaranteed to work?


Two considerations:

1) An allocator is often a zero-sized object. With proper
finagling, you can get it to occupy no space in each
vector object. Making it a static would then use *more*
space (however small), but also add a minor complication
to instantiating such a container in a DLL.

2) An allocator that is not a zero-sized object may well
have writable storage, for maintaining a per-container
pool, for example. The standard containers are not required
to accept such allocators, but the C++ Standard encourages
implementations to do so. The Dinkum C++ Library accepts
them. Making such an allocator static would then require
thread locking to avoid conflicts if more than one thread
is working with containers of the given type.

So it's probably not a good idea to make allocators static
under two circumstances:

1) if allocators are zero-sized objects

2) if allocators are not zero-sized objects

I won't comment on whether it would be better *style* to
do so.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Jul 22 '05 #2

P: n/a
"P.J. Plauger" <pj*@dinkumware.com> wrote in message news:<jg*****************@nwrddc03.gnilink.net>...
Two considerations:

1) An allocator is often a zero-sized object. With proper
finagling, you can get it to occupy no space in each
vector object. Making it a static would then use *more*
space (however small), but also add a minor complication
to instantiating such a container in a DLL.
proper finagling? hmm...(had to look up the word in the dictionary)
2) An allocator that is not a zero-sized object may well
have writable storage, for maintaining a per-container
pool, for example. The standard containers are not required
to accept such allocators, but the C++ Standard encourages
implementations to do so. The Dinkum C++ Library accepts
them. ...
Aha! So std::allocator could have private state.
Then of course its a *big* difference whether you make it
static or not. Making it static could break the code. Correct?
So it's probably not a good idea to make allocators static
under two circumstances:

1) if allocators are zero-sized objects
2) if allocators are not zero-sized objects
The following little test seems to show that
non-static member takes space, but static does not.
(gcc under cygwin):

//------------------------------------------------------------------------
#include <memory>
#include <iostream>
using namespace std;

class small { int a; };
class big { int a[200]; };

class small_alloc {
small a;
allocator<small> alloc;
};

class small_alloc_static {
small a;
static allocator<small> alloc;
};

class big_alloc {
big a;
allocator<big> alloc;
};

class big_alloc_static {
big a;
static allocator<big> alloc;
};

int main(int argc, char *argv[]) {
cout << "size(alloc<small>)=" << sizeof(allocator<small>)
<< " size(alloc<big>)=" << sizeof(allocator<big>)
<< endl;

cout << "size(small)=" << sizeof(small)
<< " size(small_alloc)=" << sizeof(small_alloc)
<< " size(small_alloc_static)=" << sizeof(small_alloc_static)
<< endl;

cout << "size(big)=" << sizeof(big)
<< " size(big_alloc)=" << sizeof(big_alloc)
<< " size(big_alloc_static)=" << sizeof(big_alloc_static)
<< endl;

return 0;
}
//---------------------------------------------------------------

The result is:
size(alloc<small>)=1 size(alloc<big>)=1
size(small)=4 size(small_alloc)=8 size(small_alloc_static)=4
size(big)=800 size(big_alloc)=804 size(big_alloc_static)=800

From this i would conclude that:

1) the gcc std::allocator<T> is a zero-sized object.
(sizeof(allocator<T>) returns 1, but i cannot imagine it
really has 1 byte of private state.)

2) the static member alloc takes _no_ space, but the non-static does.
So I'd prefer to make it a static member, unless it breaks the code.

The result could also mean that gcc cannot do "proper finagling"
(whatever that means...would you care to explain?)
I won't comment on whether it would be better *style* to
do so.


No need to comment on style.

I am coming form the traditional malloc/free() world,
*one* global allocator for *all* types of objects.

Thanks very much for your technical explanations,
which help me to better understand what a C++ std::allocator is.

Bernhard Kick.
Jul 22 '05 #3

P: n/a
"Bernhard Kick" <be***********@gmx.de> wrote in message
news:f2**************************@posting.google.c om...
2) An allocator that is not a zero-sized object may well
have writable storage, for maintaining a per-container
pool, for example. The standard containers are not required
to accept such allocators, but the C++ Standard encourages
implementations to do so. The Dinkum C++ Library accepts
them. ...
Aha! So std::allocator could have private state.
Then of course its a *big* difference whether you make it
static or not. Making it static could break the code. Correct?


In the sense that it's a sucker for race conditions in a
multithreaded environment, yes.
So it's probably not a good idea to make allocators static
under two circumstances:

1) if allocators are zero-sized objects
2) if allocators are not zero-sized objects


The following little test seems to show that
non-static member takes space, but static does not.
(gcc under cygwin):


Of course. Non-static members exist in each object, while
static members are shared across all objects and have just
one instance.
From this i would conclude that:

1) the gcc std::allocator<T> is a zero-sized object.
(sizeof(allocator<T>) returns 1, but i cannot imagine it
really has 1 byte of private state.)
It doesn't. C++ generally requires that distinct objects have
distinct addresses, so the zero-sized object is given one
padding byte to distinguish it from whatever comes next.
2) the static member alloc takes _no_ space, but the non-static does.
So I'd prefer to make it a static member, unless it breaks the code.
See multithread discussion above.
The result could also mean that gcc cannot do "proper finagling"
(whatever that means...would you care to explain?)


An exception to the rule about distinct addresses occurs for
base objects. Put a zero-sized object (alone) in a base class
and it need not have any padding. Thus it contributes nothing
to the size of the class. Our library does this trick, as do
others.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Jul 22 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.