General Allocator Regarding type definitions and void * specializedproblem | |
Hello all C++ expert programmer,
i have wrote partial general allocator for my container.
After reading standard C++ library and code guru article, i have
several questions.
1. Why allocator write forward declaration then allocation for void*
rather than directly wrote allocator first ? -
namespace std {
-
template <class Tclass allocator;
-
-
// specialize for void:
-
template <class allocator<void{
-
public:
-
typedef void* pointer;
-
typedef const void* const_pointer;
-
// reference to void members are impossible.
-
typedef void value_type;
-
template <class Ustruct rebind { typedef allocator<U>
-
other; };
-
};
-
-
template <class Tclass allocator {
-
public:
-
typedef size_t size_type;
-
typedef ptrdiff_t difference_type;
-
typedef T* pointer;
-
typedef const T* const_pointer;
-
typedef T& reference;
-
typedef const T& const_reference;
-
typedef T value_type;
-
template <class Ustruct rebind { typedef allocator<U>
-
other; };
-
-
allocator() throw();
-
allocator(const allocator&) throw();
-
template <class Uallocator(const allocator<U>&) throw();
-
~allocator() throw();
-
-
pointer address(reference x) const;
-
const_pointer address(const_reference x) const;
-
-
pointer allocate(size_type,
-
allocator<void>::const_pointer hint = 0);
-
void deallocate(pointer p, size_type n);
-
size_type max_size() const throw();
-
-
void construct(pointer p, const T& val);
-
void destroy(pointer p);
-
};
-
}
-
-
-
2. What is the use/purpose of type definition ? Quote:
1. A couple of type definitions. These ensure that the allocators'
client (for instance, 'std::vector') is able to use some relevant
types by known names. For example, consider that you write an
allocator, that is able to allocate memory in a far area, that cannot
be reached by normal pointers (let your imagination wander). Now, the
'allocator' will use some pointer-like construct. The allocators'
client has, of course, no idea of such a thing. When a client needs to
pass such a pointer it will use the
typedef T* pointer;
and if it needs to suptract such pointers, the result will have the
type 'difference_type', whatever that internally means for the
allocator.
What i understand from here is because different container needs
different pointer construct memory, therefore, there are different
member data in list and vector. So, allocator need to match back its
member data with vector for example. Quote:
typedef T* pointer; ----------- Allocator
Vector
typedef A allocator_type; typedef typename A::pointer pointer;
Although, i not able to understand what this does Quote:
vector
typedef A allocator_type; typedef typename A::pointer pointer;
3. How allocator know when it need rebind for its allocator
client(vector, list, map, set) ? Quote:
This is the magic required for std::list to work properly,
since given std::list<int( allocator<int>() ), std::list actually
needs to allocate memory for Node<int>, and not int.
Thus, they need to rebind to allocator<int>()::rebind<Node<int
:ther instead. -
template <class U>
-
struct rebind
-
{
-
typedef allocator<Uother;
-
};
-
-
list<int>;
-
-
interprete by compiler as list<int, allocator<int;
-
-
This code template <class T>
-
class allocator; is replace with allocator<int;
-
-
In other words, T(represent generic types) = int;
-
-
Then allocator class receive integer as argument
-
-
How compiler interpreter
-
template <class U>
-
struct rebind
-
{
-
typedef allocato<Uother;
-
}
-
-
How list is pass U ?
-
Thanks for your help.
Please help me.
I really appreciated any help. | | | | re: General Allocator Regarding type definitions and void * specializedproblem
This is current work. -
-
-
/*
-
Two steps define custom allocators
-
-
1. Design a memory management mechanism/model
-
2. Create standard-like allocators
-
-
-
*/
-
-
-
-
// ================================================
-
-
#ifndef _Custom_Allocator_
-
#define _Custom_Allocator_
-
-
#include <memory>
-
-
using std::allocator;
-
-
-
// ================================================
-
-
template <class T>
-
class MyAlloc
-
{
-
-
// Two Constructos which did nothing
-
public:
-
-
-
// Type Definitions
-
-
// Pointer to element type used in memory model
-
typedef T* pointer;
-
// Const Pointer to element type used in memory model
-
typedef const T* const_pointer;
-
-
// Reference to element type used in memory model
-
typedef T& reference;
-
typedef const T& const_reference;
-
-
// Type of the element that is being used in the memory model
-
typedef T value_type;
-
-
// Rpresent largest object in allocator memory model
-
typedef size_t size_type; // Unsigned
-
-
// Represent two pointer in two allocator model
-
typedef ptrdiff_t difference_type; // Signed
-
-
-
// =================================================
-
-
-
// Member Function
-
/*
-
No throw is allowed for constructor
-
and destructor
-
-
C && D is trivial(Not important)
-
-
-
*/
-
MyAlloc();
-
/*
-
Copy C is need because exception
-
specification stated that constructor
-
is not allow to throw.
-
-
Does require operator= because
-
if (this != rhs) then code will not
-
be executed and Two MyAlloc object must
-
same which form by C++ standard allocator
-
-
*/
-
MyAlloc(const MyAlloc<T&);
-
~MyAlloc();
-
-
/*
-
Require rebind because list(nodes), vector
-
(contigious)
-
-
Rebind is a structure that enables
-
an allocator for objects of one type
-
interpret as to allocate storage for
-
objects of another type.
-
-
To allocate objects of
-
different types than its
-
template parameter
-
-
The rebind member allows a container
-
to construct an allocator for some
-
arbitrary type out of the allocator type
-
provided as a template parameter.
-
-
This is the magic required
-
for std::list to work properly,
-
since given std::list<int>
-
( allocator<int>() ),
-
std::list actually needs to allocate memory
-
for Node<int>, and not int.
-
Thus, they need to rebind to
-
-
-
allocator<int>()::rebind<Node<int
-
::other instead.
-
-
-
For instance, the list container gets an
-
allocator<Tby default, but a list may
-
well need to allocate list_nodes as well
-
as T's. The container can construct an
-
allocator for list_nodes out of the
-
allocator for T's
-
(the template parameter,
-
Allocator, in this case) as follows:
-
-
Allocator::rebind<list_node>
-
::other list_node_allocator;
-
-
*/
-
-
/*
-
Explicit call by compiler is
-
allocator<T>::rebind<U>::other;
-
-
Here allocator client(vector, list)
-
request allocator type from allocator
-
-
Therefore, allocator using rebind to
-
preseve the old state type and duplicate
-
a same/new state type to pass to
-
allocator client.
-
-
Then, continue to class to rework a new
-
type which is
-
listAllocator < node<int and
-
not allocator<int>.
-
-
-
*/
-
template <class U>
-
struct rebind
-
{
-
typedef allocator<Uother;
-
}
-
-
-
-
// Return address of given object
-
pointer address(reference x) const;
-
const_pointer address(const_reference x) const;
-
-
// Returns the largest value which can be passed to the 'allocate()'
-
function.
-
size_type MaxMemory();
-
-
/*
-
Returns storage for n elements of
-
the element type being used
-
in the memory model.
-
-
Elements will not be c
-
onstructed/initialized.
-
-
*/
-
pointer allocate(size_type);
-
/*
-
Deallocate element type used in
-
memory model begin at position p
-
-
Storage must be allocate by same allocator
-
-
Size must same in allocate()
-
p must not be 0.
-
Elements must have been destroyed before.
-
*/
-
void deallocate(pointer, size_type);
-
-
/*
-
Allocate must call before construct
-
This is a call to placement new
-
value is U
-
new((void*)p) T(u);
-
*/
-
void construct(pointer, const_reference);
-
/*
-
Destrory call ahead of (prior to) deallocate
-
new((void*)p) T(u);
-
*/
-
void destrory(pointer);
-
};
-
-
/*
-
No refernce type to void* -That's why need
-
specialization for void.
-
*/
-
-
// ================================================
-
-
template<class T1, class T2>
-
bool operator==(MyAlloc<T1>, MyAlloc<T2>) const
-
{
-
return MyAlloc<T1== MyAlloc<T2>;
-
}
-
-
template<class T1, class T2>
-
bool operator!=(MyAlloc<T1>, MyAlloc<T2>) const
-
{
-
return MyAlloc<T1!= MyAlloc<T2>;
-
}
-
-
// ================================================
-
-
-
-
#endif
-
-
/*
-
-
allocate and deallocate function are
-
low level memory management which
-
doesn't participate in
-
object construction and destruction.
-
-
The purpose of the allocator is to allocate
-
raw memory without construction of objects,
-
as well as simply deallocate memory
-
without the need to destroy them.
-
-
Usage of ::operator new and ::operator delete
-
is preferred over keywords new and delete.
-
-
A* a = new A;
-
delete a;
-
-
Intepreted by compiler as below:
-
-
// assuming new throws std::bad_alloc upon failure
-
-
Allocate then construct
-
A* a = ::operator new(sizeof(A));
-
a->A::A();
-
-
if ( a != 0 )
-
{ // a check is necessary for delete
-
-
a->~A();
-
::operator delete(a);
-
-
Destroyed(Destruct) first
-
before deallocate
-
}
-
-
-
Every C++ standard like allocator must provide
-
these global operator== and operator!=
-
-
Memory Model are shared model, grabage collection,
-
segregrated model.
-
-
Why write custom allocators ?
-
1. To trace the memory operations of
-
your application to a file
-
2. Speed
-
-
-
-
Sample Override New and delete Code
-
-
void* operator new(size_t,void* anAddress)
-
{
-
return anAddress;
-
}
-
void* operator new(size_t size)
-
{
-
return Standard::Allocate(size);
-
}
-
void operator delete(void *anAddress)
-
{
-
if (anAddress)
-
Standard::Free((Standard_Address&)anAddress);
-
}
-
-
The first new operator overload is for the
-
new with placement syntax, instead of
-
creating instances on the free store it
-
will use the address you provided.
-
-
This is useful for using preallocated memory (e.g. a buffer)
-
to store your objects and still have the
-
construtors and destructors called for these
-
objects.
-
-
Apparently this first overload is just the
-
default one that would be generated by
-
the compiler anyway.
-
-
-
The second new and the delete operator overload are apparently
-
defined because the coder wanted to use a custom allocator.
-
If the first new overload seems useless but is still present it may
-
be that the compiler is requiring it if you overload the new(size_t)
-
one ( just a guess), try removing the new(size_t, void*) definition
-
and see if the code still compiles and link.
-
-
-
No reference to object which allocated on the stack
-
This is make sense since stack unwinding
-
will get clean up and you will use danling
-
reference
-
-
Never pass auto_ptrs by value
-
if a function can throw
-
-
-
BTW, returning auto_ptrs by value is a
-
good idea for factory and
-
clone like functions.
-
*/
-
-
-
-
-
-
-
-
// Sketch version of list
-
-
/*
-
template <typename T, typename A>
-
class node
-
{
-
typedfed node list_nodes;
-
-
typename A::rebind<list_nodes>::others listNodeAllocator;
-
// Actually declare listNodeAllocator < list_nodes<T;
-
-
};
-
-
*/
-
Thanks for your correction. | | | | re: General Allocator Regarding type definitions and void * specializedproblem
You can not change or add code to std namespace because it is
undefined behaviour. | | | | re: General Allocator Regarding type definitions and void * specializedproblem
I didn't add to code to namespace standard.
I create my custom allocator with my own namespace.
Please behave in C++ usenet community.
Thanks. | | | | re: General Allocator Regarding type definitions and void * specializedproblem
Please help me. | | | | re: General Allocator Regarding type definitions and void * specializedproblem
This is all my code.
What should i do for next steps ?
Thanks for your help. | | | | re: General Allocator Regarding type definitions and void * specializedproblem
I have corrected my code.
Now my problem is this: Quote:
Error 1 error C2440: 'default argument' : cannot convert from
'MyAllocator<T>' to 'MyAllocator<T>' c:\program files\microsoft visual
studio 8\vc\include\list 83
Please help me. | | | | re: General Allocator Regarding type definitions and void * specializedproblem | | | | re: General Allocator Regarding type definitions and void * specializedproblem
Please help me. | | | | re: General Allocator Regarding type definitions and void * specializedproblem PeterAPIIT@gmail.com wrote:
[...] Quote:
template <class T>
class MyAllocator
{
public:
>
// Type Definitions
>
typedef T value_type;
[...more types...] Quote:
>
// Member Function
>
MyAllocator(){}
>
template <class U>
MyAllocator(const MyAllocator<T&rhs){}
^^^
The template parameter U is not used. Do you mean this instead?
template <class U>
MyAllocator(const MyAllocator<U&rhs){}
[...] Quote:
// ============== Global Functions ===============
>
// Non member function cannot declare as constant
You cannot declare the functions as constant, but the parameter: Quote:
template<class T1, class T2>
bool operator==(MyAllocator<T1>& first, MyAllocator<T2>& second)
bool operator==(const MyAllocator<T1>& first, const MyAllocator<T2>& second) Quote:
{
return first == second;
What function should be called here? The function will call itself. This
is infinite recursion. Quote:
}
>
template<class T1, class T2>
bool operator!=(MyAllocator<T1>& first, MyAllocator<T2>& second)
{
return first!=second;
}
Same as above.
--
Thomas | | | | re: General Allocator Regarding type definitions and void * specializedproblem PeterAPIIT@gmail.com wrote: We can't help if we don't know your problem.
If your code doesn't compile, write what error messages you get, and on
which line of code the error is.
If your code compiles but doesn't work, tell us what you expect and what
did you get instead.
Also see here: http://www.parashift.com/c++-faq-lit...t.html#faq-5.8
--
Thomas | | | | re: General Allocator Regarding type definitions and void * specializedproblem
Why cannot use "using" in header file ?
how do resolve the operator == and operator!= ?
Thanks for your help. | | | | re: General Allocator Regarding type definitions and void * specializedproblem
Another error is Quote:
Error 1 error C2146: syntax error : missing ';' before identifier
'aPtr' d:\c++\custom allocator\custom allocator\custom_allocator.h 87
Warning 2 warning C4551: function call missing argument list d:\c++
\custom allocator\custom allocator\custom_allocator.h 87 for this code -
void deallocate(pointer aPtr, size_type allocateSize)
-
{
-
if (aPtr != 0)
-
{
-
destroy(aPtr);
-
::operator delete aPtr[allocateSize];
-
}
-
}
-
-
-
This is my complete code: | | | | re: General Allocator Regarding type definitions and void * specializedproblem
On 2008-09-07 11:27, PeterAPIIT@gmail.com wrote: Quote:
Why cannot use "using" in header file ?
Since you have not quoted the part you are replying to I can only guess
you meant "why can I not use "using namespace" in a header file?" and
the answer is that you can, but it is bad. The reason is simple, every
file that included your header will get the effects of the "using
namespace", consider the following:
------ Test.h -----
#ifndef TEST_H
#define TEST_H
#include <iostream>
using namespace std;
void foo()
{
std::cout << "foo()\n";
}
#endif
------ Test.cpp -----
#include <vector>
#include "Test.h"
template<typename T>
class vector
{
T t;
};
int main()
{
vector<intv; // Error
}
The problem is that the "using namespace std;" in Test.h" is in effect
in Test.cpp, and vector<intcan now refer to your class or std::vector.
In some cases you might get even worse problems because you do not get
an ambiguity and instead you use some type/function which you did not
intend to use, and the only clue is that the program does not work as it
should.
Therefore you should avoid "using namespace" in headers.
--
Erik Wikström | | | | re: General Allocator Regarding type definitions and void * specializedproblem Quote:
"why can I not use "using namespace" in a header file?"
Are you trying to explain that name clashed between user defined code
and standard namespace ?
After listen to you advise, i guess we can include any header file in
our own header file but cannot using whole namespace instead explicit
specify which function or class to use.
In the example you given, compiler cannot resolve vector defined by us
ans std. Therefore, an ambiguity has occurred.
Am i correct ?
Another question is how about code at below ? -
pointer allocate(size_type allocateSize)
-
{
-
return static_cast<pointer(::operator new (allocateSize));
-
}
-
-
void deallocate(pointer aPtr, size_type allocateSize)
-
{
-
if (aPtr != 0)
-
{
-
destroy(aPtr);
-
::operator delete aPtr[allocateSize];
-
}
-
}
-
-
void construct(pointer aPtr, const_reference value)
-
{
-
if (aPtr != 0)
-
{
-
// ((void *)aPtr) is placement new
-
// T(value) convert to T type
-
::operator new ((void *)aPtr) T(value);
-
}
-
}
-
void destroy(pointer aPtr)
-
{
-
if (aPtr != 0)
-
{
-
aPtr->~MyAllocator<T>;
-
}
-
}
-
-
template<class T1, class T2>
-
bool operator==(const MyAllocator<T1>& first,
-
const MyAllocator<T2>& second)
-
{
-
return true;
-
}
-
-
template<class T1, class T2>
-
bool operator!=(const MyAllocator<T1>& first,
-
const MyAllocator<T2>& second)
-
{
-
return false;
-
}
-
-
-
What code is need to add ?
A billion thanks for your help. | | | | re: General Allocator Regarding type definitions and void * specializedproblem
Yet another question is when i try to compile my code.
It shown my error : -
void destroy(pointer aPtr)
-
{
-
if (aPtr != 0)
-
{
-
aPtr->~MyAllocator<T>;
-
}
-
}
-
-
error C2325: 'MyAllocator<T>' : unexpected type to the right of '->~':
-
expected 'std::_List_nod<_Ty,_Alloc>::_Node '
-
-
-
void construct(pointer aPtr, const_reference value)
-
{
-
if (aPtr != 0)
-
{
-
// ((void *)aPtr) is placement new
-
// T(value) convert to T type
-
::operator new ((void *)aPtr) T(value);
-
}
-
}
-
-
error C2665: 'operator new' : none of the 5 overloads could convert
-
all the argument types
-
error C2146: syntax error : missing ';' before identifier 'T'
-
-
-
-
void deallocate(pointer aPtr, size_type allocateSize)
-
{
-
if (aPtr != 0)
-
{
-
destroy(aPtr);
-
::operator delete aPtr[allocateSize];
-
}
-
}
-
-
error C2146: syntax error : missing ';' before identifier 'aPtr'
-
warning C4551: function call missing argument list
-
-
-
-
A billion thanks for your help. | | | | re: General Allocator Regarding type definitions and void * specializedproblem
This is my intention of my code -
void deallocate(pointer aPtr, size_type allocateSize)
-
{
-
if (aPtr != 0)
-
{
-
destroy(aPtr);
-
// ::operator delete aPtr[allocateSize];
-
-
// I want delete the memory of container
-
}
-
}
-
-
void construct(pointer aPtr, const_reference value)
-
{
-
if (aPtr != 0)
-
{
-
// ((void *)aPtr) is placement new
-
// T(value) convert to T type
-
::operator new ((void *)aPtr) T(value);
-
-
// I want to do placement new to initialize the memory which has
-
allocated
-
}
-
}
-
void destroy(pointer aPtr)
-
{
-
if (aPtr != 0)
-
{
-
aPtr->~MyAllocator<T>;
-
// I want to do uninitialize the container value hold.
-
-
}
-
}
-
-
A billion thanks for your help. |  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,510 network members.
|