在其他地方,建议使用仿函数来删除向量中的指针
struct DeleteFromVector
{
template <class T>
void operator() ( T* ptr) const
{
delete ptr;
}
};
使用
进行调用std::for_each(aVec.begin(), aVec.end(), DeleteFromVector());
我写了类似的东西(虽然最初没有在结构中巧妙地移动模板):
struct DeleteObj
{
template<typename ObjType>
inline void operator() (ObjType obj)
{
delete obj;
obj = NULL;
};
};
在调试器中单步执行它似乎工作,即obj被识别为指针而没有任何崩溃。
我有点困惑为什么两者都有效,并且还希望听到有关使用const和内联的意见。
谢谢, 罗伯特
答案 0 :(得分:3)
第一个是首选,因为只有在向量元素类型是指针时才会编译。如果向量元素类型可以转换为非void指针,则第二个将编译,可能会产生灾难性后果。
Functors通常被声明为const,通常不会有所作为,但它也不会花费任何费用。
答案 1 :(得分:2)
它有效,因为ObjType
推断为WhateverTypeYouHaveInYourVector *
。使用第一个解决方案,T
推断为WhateverTypeYouHaveInYourVector
。后者更好,因为它要求参数是一个指针,而在你的解决方案中,参数可以是任何东西,甚至是不可删除的东西。
顺便说一下,obj = NULL
没用,因为你按值取参数。因此,将设置为null的指针是函数的本地副本,而不是向量中包含的副本。您可以改为引用指针:
struct Deleter
{
template <typename T>
void operator()( T * & ptr) const
{
delete ptr;
ptr = 0;
}
};
答案 2 :(得分:2)
为什么两者都有效:如果您致电operator()(U*)
,则第一个与T = U
匹配,第二个与ObjType = U*
匹配。
const
:这只是说你没有修改任何成员,但由于你的结构是空的,这没什么区别。有些算法可能将其函子作为const,因此只允许访问常量成员函数(但不能在for_each
中)。无论如何,你的成员函数也可能是静态的,因为没有状态。
内联只是一个编译器提示;无论如何,建筑都会被内联。无论如何,类定义中的成员定义都是隐式内联的。
答案 3 :(得分:2)
为什么两个模板都有效?
在第一个模板中,您将Obj*
传递给采用T*
的模板方法,以便编译器推断T
为Obj
。
在第二个模板中,您将Obj*
传递给采用T
的模板方法,以便编译器推断T
为Obj*
。
使用inline
inline
在那里是多余的,因为类定义中的成员函数已定义是隐式的inline
。
使用const
如果可能,Functors应将operator()
声明为const
。这是因为通过非const引用传递临时是非法的。除非std::for_each(...,..., Functor());
具有Functor
,否则对operator(T)const
的调用可能无法编译。
由于Microsoft编译器实现了非标准扩展,允许通过非const引用传递临时值并默认启用此非标准行为,因此该问题变得混乱。
答案 4 :(得分:1)
两者都有效,因为两者都正确地推导出了模板参数,只是在一种情况下它是一个指针,在另一种情况下它是指向的类型,因为签名已经包含*
内联在这里是多余的,因为函数已经内联。设置obj = NULL
也没用,因为它只将指针的本地副本设置为0,而不是 - 很可能
意图 - 向量中的条目。
答案 5 :(得分:0)
第二个例子可能不起作用,因为你没有指出它:
inline void operator() (ObjType* obj)
这应该有效,就像上面的例子一样。
inline
是一个编译器优化建议,可以将函数完全复制到每个被调用的地方。
const
关键字有很多用途,具体取决于您使用它的位置。在您的情况下(在第一个示例中),意味着调用该方法的类或对象不得更改,并且可以在const
上下文中使用。