views:

216

answers:

4

For what purpose I should use std::get_temporary_buffer? Standard says the following:

Obtains a pointer to storage sufficient to store up to n adjacent T objects.

I thought that the buffer will be allocated on the stack, but that is not true. According to the C++ Standard this buffer is actually not temporary. What advantages does this function have over the global function ::operator new, which doesn't construct the objects either. Am I right that the following statements are equivalent?

int* x;
x = std::get_temporary_buffer<int>( 10 ).first;
x = static_cast<int*>( ::operator new( 10*sizeof(int) ) );

Does this function only exist for syntax sugar? Why is there temporary in its name?


One use case was suggested in the Dr. Dobb's Journal, July 01, 1996 for implementing algorithms:

If no buffer can be allocated, or if it is smaller than requested, the algorithm still works correctly, It merely slows down.

+4  A: 

The standard says it allocates storage for up to n elements. In other words, your example might return a buffer big enough for 5 objects only.

It does seem pretty difficult to imagine a good use case for this though. Perhaps if you're working on a very memory-constrained platform, it's a convenient way to get "as much memory as possible".

But on such a constrained platform, I'd imagine you'd bypass the memory allocator as much as possible, and use a memory pool or something you have full control over.

jalf
+2  A: 
ptrdiff_t            request = 12
pair<int*,ptrdiff_t> p       = get_temporary_buffer<int>(request);
int*                 base    = p.first;
ptrdiff_t            respond = p.sencond;
assert( is_valid( base, base + respond ) );

respond may be less than request.

size_t require = 12;
int*   base    = static_cast<int*>( ::operator new( require*sizeof(int) ) );
assert( is_valid( base, base + require ) );

the actual size of base must greater or equal to require.

OwnWaterloo
+7  A: 

Stroustrup says in "The C++ Programming Language" (§19.4.4, SE):

The idea is that a system may keep a number of fixed-sized buffers ready for fast allocation so that requesting space for n objects may yield space for more than n. It may also yield less, however, so one way of using get_temporary_buffer() is to optimistically ask for a lot and then use what happens to be available.
[...] Because get_temporary_buffer() is low-level and likely to be optimized for managing temporary buffers, it should not be used as an alternative to new or allocator::allocate() for obtaining longer-term storage.

He also starts the introduction to the two functions with:

Algorithms often require temporary space to perform acceptably.

... but doesn't seem to provide a definition of temporary or longer-term anywhere.

Georg Fritzsche
Looks like VC++'s implementation of this is simply a loop calling `operator new` with successively smaller arguments until the allocation succeeds. No special optimizations there.
jalf
@jalf, the same code in g++ 4.2.4.
Kirill V. Lyadvinsky
Same with g++ 4.5 - seems it was well-intended but ignored by the vendors.
Georg Fritzsche
A: 

If you are not affraid of using real standard library (C++ without the ++) then why not use alloca()?

At least, what alloca() does is pretty well-known and is not going to change because a commettee decided that the previous C++ specifications were inappropriate... (yes, it happened several times for the ++).

Pierre
Standard Library was described in the C++ Standard ISO/IEC14882:2003 as all other parts. It doesn't contain `alloca` function. And my question wasn't about 'how to allocate memory on the stack'.
Kirill V. Lyadvinsky
@Pierre: which previous changes in the C++ spec are you referring to? And what guarantees can you offer that `alloca` won't be changed in a future revision of C?
jalf