Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以在C++;每个单元的via<;算法>;?_C++_Memory_Foreach_Delete Operator - Fatal编程技术网

C++ 我可以在C++;每个单元的via<;算法>;?

C++ 我可以在C++;每个单元的via<;算法>;?,c++,memory,foreach,delete-operator,C++,Memory,Foreach,Delete Operator,假设我有一个std::vector objs(出于性能原因,我的指针不是实际的Objs) 我用obj.push_back(新的obj(…))填充它重复 完成后,我必须删除后推的元素。一种方法是: for (std::vector<Obj *>::iterator it = objs.begin(); it != objs.end(); ++it) { delete *it; } 你觉得怎么样?是的,但你需要一个函子: struct delete_ptr { temp

假设我有一个
std::vector objs
(出于性能原因,我的指针不是实际的
Obj
s)

我用
obj.push_back(新的obj(…))填充它重复

完成后,我必须
删除
后推的元素。一种方法是:

for (std::vector<Obj *>::iterator it = objs.begin(); it != objs.end(); ++it) {
    delete *it;
}

你觉得怎么样?

是的,但你需要一个函子:

struct delete_ptr
{
    template <typename T>
    void operator()(T* pPtr)
    {
        delete pPtr;
    }
};

std::for_each(objs.begin(), objs.end(), delete_ptr());


然而,面对例外情况,这是危险的

您的问题是
删除
不是一个函数,而是一个关键字,因此您无法获取它的地址

在C++0x中,将有一个
std::default\u delete
类(由
std::unique\u ptr
使用),您可以使用该类,或者正如大家所说的那样,自己编写一个类是微不足道的(如果您试图删除不完整的类型,标准类也会引发编译错误)

#包括
#包括
#包括
int main()
{
std::vec;
std::for_each(vec.begin()、vec.end()、std::default_delete());
}
虽然您可以这么做(),但拥有带有指向所拥有资源的裸指针的容器是一种强烈的代码味道。例如,在此代码中:

  void foo()
  {
    std::vector<Obj *> bar;
    fill(bar);
    use(bar);
    std::for_each(objs.begin(), objs.end(), delete_ptr()); // as GMan suggests
  }

对于_,每个
都需要一个函数指针或函数对象。对于内存释放,您可以尝试
&::operator delete
,它将获取释放内存的函数的地址。但是,当您使用delete语句时,编译器会在调用
运算符delete(void*)
之前调用析构函数,因此清除实际上不是
运算符delete(void*)
函数的一部分


使用仿函数ala GMan的答案。

不完全正确
for_每个
都需要一个可以用
()
调用的函数或对象,而
delete既不是函数也不是对象。您必须将其封装在函数(或函数对象)中,可能类似于:

struct Deleter
{
    void operator()(Obj* obj) {delete obj;}
};

std::for_each(objs.begin(), objs.end(), Deleter());
但您应该非常小心地使用原始指针管理对象生命周期,尤其是在传递它们时。如果您从
向量中删除它们,或者重新分配它们,或者如果您清除
向量,或者如果异常、中断或函数返回可能导致向量被破坏,则需要记住删除它们。一般来说,最好将资源管理和资源使用的责任分开

最好使用对象向量,除非
Obj
是一个多态基类,或者对象确实太大或太复杂,复制它们会对性能产生显著影响。如果是这种情况(并且你已经确定了它的情况),那么你应该考虑一个智能指针的矢量(<代码> SydDypPTR<代码>,或者如果你的编译器支持它,代码> UnQuyPPTR <代码>,或者Boost的<代码> pTrvector矢量< /C>

养成使用自动资源管理类的习惯将在将来为您省去很多麻烦。

您可以通过将
共享的ptr
存储在向量中,或者使用boost的
ptr\u向量
(请参阅)来完全消除删除问题。

是的。用智能指针填充它并使用vector.clear()是最简单的方法。

对于每个_
都不应该修改您正在迭代的集合。@KennyTM:不是,指针值保持不变。(同样,这个要求在C++0x中被取消。)@GMan:我相信你是正确的,但是你有引用(这是我想读的)。@Martin:当然,§25.2.4/2:“效果:将f应用于从first开始到last-1范围内的每个迭代器的解引用结果。[注:如果first类型满足可变迭代器的要求,f可以通过解引用迭代器应用非恒定函数。-结束注]“注是重要部分。所有答案都很好,谢谢大家!我赢了。”​​​​​​) 但我喜欢你的格式,让我们形成一个循环依赖关系。@GMan:Garrghh!你让我陷入了一个循环。Grrr。我很想知道为什么这被否决了。有什么问题吗?@sbi:在你发布答案之前,我已经把你的答案放在我的答案里了。所以我“赢得了[比赛]”.但我更喜欢你的,所以我把它们循环在一起。@GMan:哦,我甚至都没见过。循环是一件邪恶的事情。(就像谷歌搜索“递归”。)格曼先生,你能解释一下functor的用法吗?特别是,为什么普通的
delete
不起作用?谢谢。@bodacydo:
delete
在语言层面上不起作用的原因是它是一个关键字,你不能将关键字传递到函数中。你不能用
delete
调用它,就像用
catch调用它一样de>或
static\u cast
(函数需要传递变量。函子和函数指针就是这样。)啊,我正要问为什么没有人演示如何使用lambda来实现这一点,这时我发现我错过了你的。
:)
非常有见地,谢谢。我从来没有想过自己会使用
&::操作符delete
。(我也知道它不会调用我对象的析构函数)。@bodacydo:你说得对,这不会调用析构函数。这只能用于释放原始内存块,而不能用于删除对象。我想
操作符+
(我相信可以与
std::foreach()
一起使用)then不是一个关键字,而是一个函数的名称,它的名称恰好由一个关键字和一个运算符组成?@sbi:那会是什么样子?据我所知,如果你想使用
operator+
,那么你需要的函数对象叫做
std::plus
(是的,
operatorX
是一个函数,除了内置类型。)@UncleBens:你是说我们不能获取一个恰好是运算符的函数的地址吗?@sbi:你可以这样做:
&some\u type::operator+
,是的。@sbi:我的意思是当你做类似于
std::foreach(a,b,static\u cast)(&operator)的事情时
#include <vector>
#include <algorithm>
#include <memory>

int main()
{
    std::vector<int*> vec;
    std::for_each(vec.begin(), vec.end(), std::default_delete<int>());
}
  void foo()
  {
    std::vector<Obj *> bar;
    fill(bar);
    use(bar);
    std::for_each(objs.begin(), objs.end(), delete_ptr()); // as GMan suggests
  }
std::vector< std::shared_ptr<Obj> > bar;
struct Deleter
{
    void operator()(Obj* obj) {delete obj;}
};

std::for_each(objs.begin(), objs.end(), Deleter());