c++ functor for deleting pointers seems to work
Elsewhere the following was suggested for a functor for deleting pointer开发者_如何学运维s in a vector
struct DeleteFromVector
{
template <class T>
void operator() ( T* ptr) const
{
delete ptr;
}
};
to be called using
std::for_each(aVec.begin(), aVec.end(), DeleteFromVector());
I had written something similar (though originally without the clever moving of the template within the struct):
struct DeleteObj
{
template<typename ObjType>
inline void operator() (ObjType obj)
{
delete obj;
obj = NULL;
};
};
Stepping through it in the debugger it seems to work, i.e. obj is recognized as a pointer and nothing crashes.
I'm a bit confused as to why both work, and would also like to hear opinions on the use of const and inline in these.
Thanks, Robert
The first is to be preferred since it will only compile if the vector element type is a pointer. The second would compile if the vector element type is convertable to a non-void pointer, with presumably disasterous consequences.
Functors are normally declared const, doesn't often make a difference but it doesn't cost anything either.
Why do both templates work?
In the first template, you pass an Obj*
to a template method taking a T*
so the compiler deduces that T
is Obj
.
In the second template, you pass an Obj*
to a template method taking a T
so the compiler deduces that T
is Obj*
.
Use of inline
The inline
is redundant there, as member functions defined inside the class definition are implicitly inline
.
Use of const
Functors should have their operator()
declared const
if possible . This is because it is illegal to pass a temporary by non-const reference. A call to std::for_each(...,..., Functor());
may not compile unless Functor
has an operator(T)const
.
This issue is muddied by the fact that the Microsoft compilers implement a non-standard extension allowing passing temporaries by non-const reference and enable this non-standard behaviour by default.
Why both work: If you call
operator()(U*)
, the first one matchesT = U
, the second one matchesObjType = U*
.const
: that just says that you're not modifying any members, but since your structs are empty, this makes no difference. Some algorithms may take their functors as const and hence allow only access to constant member functions (but not infor_each
). In any event, your member function might as well be static, since the there's no state.inlining is just a compiler hint; chances are that construction would be inlined no matter what. Member definitions inside class definitions are implicitly inline anyway.
It works because ObjType
is deduced to be WhateverTypeYouHaveInYourVector *
. With the first solution, T
is deduced to be WhateverTypeYouHaveInYourVector
. The latter is better because it requires the argument to be a pointer, while in your solution, the argument can be anything, even something that is not deletable.
By the way, obj = NULL
is useless because you take the parameter by value. Consequently, the pointer that will be set to null is the copy local to the function, not the one contained in the vector. You could take a reference to a pointer instead:
struct Deleter
{
template <typename T>
void operator()( T * & ptr) const
{
delete ptr;
ptr = 0;
}
};
Both work because both properly deduce the template parameter, just in one case it is a pointer, in the other it is the type that is being pointed to, because the signature already contains the *
inline is redundant here, as the function is inline already. Also setting the obj = NULL
is useless since it sets only your local copy of the pointer to 0, not -- as was probably
intended -- the entry in the vector.
The second example may not work, because you did not make a pointer out of it:
inline void operator() (ObjType* obj)
This should work, just as the upper example.
The inline
is a compiler optimization suggestion to completely copy the function to every place it is called.
The const
keyword has many uses, depending on where you use it. In your case (in the first example) it means, that the class or object on which the method is called shall not alter and can be used in const
contexts.
精彩评论