开发者

c++ functor for deleting pointers seems to work

开发者 https://www.devze.com 2023-03-28 22:08 出处:网络
Elsewhere the following was suggested for a functor for deleting pointer开发者_如何学运维s in a vector

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 constif 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 matches T = U, the second one matches ObjType = 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 in for_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.

0

精彩评论

暂无评论...
验证码 换一张
取 消