使用 std::unary_function 清除指针 std::vector
Clearing std::vector of pointers with std::unary_function
迈耶斯在他的 "Effective STL" 中展示了如何正确清理指针向量(std::vector::clear
只删除他的指针,而不删除它们占用的内存)。
所以他建议在调用 clear
之前使用 for_each
和 unary_function 调用对象析构函数:
template<typename T> struct DeleteMyObject2: public std::unary_function<const T*, void>
{
void operator()(const T* ptr);
};
template<> struct DeleteMyObject2<algotest::ImageSelection>
{
void operator()(const algotest::ImageSelection* ptr)
{
delete ptr;
ptr=0; // this was added by me
}
};
void std_clearing_pointers()
{
std::vector<ImageSelection*> vec;
vec.reserve(5);
for(int i=0; i<5; ++i)
vec.insert(vec.begin(), new ImageSelection());
std::for_each(vec.begin(), vec.end(), DeleteMyObject2<ImageSelection>());
// HERE elements of vec are not NULL !!!
vec.clear();
}
在书中 DeleteMyObject2
被调用时没有括号,它没有编译(问题 1:为什么?标准被改变了吗?):
std::for_each(vec.begin(), vec.end(), DeleteMyObject2<ImageSelection>);
无论如何,如果为 DeleteMyObject2
调用 operator()
,但在 vec.clear()
之前 vector 中的对象不是 NULL,它会编译。我想当 STL 容器一直在复制它们的元素时,ImageSelection
指针是按值传递的,所以一切都很好(问题 2:我说得对吗?)。
我尝试通过 ref 传递指针,现在对象在 for_each
之后是 NULL,我感觉更安全。
template<> struct DeleteMyObject1<algotest::ImageSelection>
{
void operator()(algotest::ImageSelection*& ptr)
{
delete ptr;
ptr=0;
}
};
问题3: DeleteMyObject2
是否比DeleteMyObject1
更可取,因为它没有不必要的赋值?
提前致谢。
自从 Effective STL 问世以来,就有了更短、更易读的方法来做到这一点。例如,您现在可以写
vector<int *> a{new int{1}, new int{2}};
for_each(begin(a), end(a), [](int *p){delete p;});
其中 [](int *p){delete p;}
是一个 lambda or, anonymous, function 对 delete
任何 p
的说法,其代码比您问题中的任何一个 class 都短得多。
顺便说一句,您可能还想考虑 vector
智能指针(例如,vector<shared_ptr<int>>
用于指向整数的指针向量)。用于释放资源的显式代码容易出错。
关于您的问题:
class 应该 出现在括号中,用它表明你想要这个 [=37= 的(默认构造的)对象].该函数需要一个对象,而不是 class.
按值传递指针是可以的(在本例中)。
迈耶斯在他的 "Effective STL" 中展示了如何正确清理指针向量(std::vector::clear
只删除他的指针,而不删除它们占用的内存)。
所以他建议在调用 clear
之前使用 for_each
和 unary_function 调用对象析构函数:
template<typename T> struct DeleteMyObject2: public std::unary_function<const T*, void>
{
void operator()(const T* ptr);
};
template<> struct DeleteMyObject2<algotest::ImageSelection>
{
void operator()(const algotest::ImageSelection* ptr)
{
delete ptr;
ptr=0; // this was added by me
}
};
void std_clearing_pointers()
{
std::vector<ImageSelection*> vec;
vec.reserve(5);
for(int i=0; i<5; ++i)
vec.insert(vec.begin(), new ImageSelection());
std::for_each(vec.begin(), vec.end(), DeleteMyObject2<ImageSelection>());
// HERE elements of vec are not NULL !!!
vec.clear();
}
在书中 DeleteMyObject2
被调用时没有括号,它没有编译(问题 1:为什么?标准被改变了吗?):
std::for_each(vec.begin(), vec.end(), DeleteMyObject2<ImageSelection>);
无论如何,如果为 DeleteMyObject2
调用 operator()
,但在 vec.clear()
之前 vector 中的对象不是 NULL,它会编译。我想当 STL 容器一直在复制它们的元素时,ImageSelection
指针是按值传递的,所以一切都很好(问题 2:我说得对吗?)。
我尝试通过 ref 传递指针,现在对象在 for_each
之后是 NULL,我感觉更安全。
template<> struct DeleteMyObject1<algotest::ImageSelection>
{
void operator()(algotest::ImageSelection*& ptr)
{
delete ptr;
ptr=0;
}
};
问题3: DeleteMyObject2
是否比DeleteMyObject1
更可取,因为它没有不必要的赋值?
提前致谢。
自从 Effective STL 问世以来,就有了更短、更易读的方法来做到这一点。例如,您现在可以写
vector<int *> a{new int{1}, new int{2}};
for_each(begin(a), end(a), [](int *p){delete p;});
其中 [](int *p){delete p;}
是一个 lambda or, anonymous, function 对 delete
任何 p
的说法,其代码比您问题中的任何一个 class 都短得多。
顺便说一句,您可能还想考虑 vector
智能指针(例如,vector<shared_ptr<int>>
用于指向整数的指针向量)。用于释放资源的显式代码容易出错。
关于您的问题:
class 应该 出现在括号中,用它表明你想要这个 [=37= 的(默认构造的)对象].该函数需要一个对象,而不是 class.
按值传递指针是可以的(在本例中)。