很多时候我们需要在循环中初始化某些类的对象来进行操作:
假设我有一个类/结构:
class employee
{
//member variables
//member methods - getter/setters,etc
}
现在假设我想对阵列中的每个员工进行操作。
方法1:
for (loop on array of 10 employees)
{
employee emp(loop element); //using constructor of employee for initialization
//operate on the current loop element using emp
}
这样,根据我的理解,将创建10个emp对象,直到循环结束。现在,由于这不包括动态内存分配,一旦控件退出循环,将删除所有10个对象(& memory占用10将被释放)或只是最后一个对象将被删除(并且9个对象占用的内存不会被释放)。
方法2:
for (loop on array of 10 employees)
{
employee *emp=new employee(loop element); //using constructor of employee for initialization
//operate on the current loop element using emp
delete emp;
emp = nullptr;
}
这是程序员的控制,所以我们可以在循环的每次迭代中自己释放内存。虽然这也会导致频繁的分配和释放堆内存&如果循环适用于大量员工,可能会导致一些降级。
请帮助我解决方法1和方法中提到的问题。请建议上述哪种方法是好的,如果有更好的方法呢?
答案 0 :(得分:1)
方法1更好,因为您不需要依赖于delete
与delete
的平衡,因此它不太可能泄漏内存:如果您的"操作上"代码是在方法2中引发异常然后employee
将不被调用。在方法1中,如果在堆栈展开时抛出异常,则会调用析构函数
从概念上讲,是的,在两个方法中,将在循环的每个单独迭代中调用<img src="<?php echo wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), 'medium');?>">
的析构函数。也就是说,允许编译器将此作为优化策略,如果没有副作用。
答案 1 :(得分:1)
我不确定我是否理解这个问题。如果我有一个循环对象,我不想修改对象,我不会复制它们。我只想使用const引用。
for(auto const& e: employees) {
// operate on e
}
如果对象被修改,即调用非const成员函数,我将使用非const引用
for(auto&& e: employees) {
// operate on e
}
在您的示例中,“临时”员工对象是堆栈或堆分配的。在第一种情况下,在堆栈上创建对象。这意味着编译器只是将堆栈指针增加(或减少)为一个值,即堆栈上有足够的空间来容纳雇员对象,然后使用构造函数对其进行初始化。不会进行堆分配,并且只有一个Employee类型的对象加上循环中的对象。范围结束时,生命周期结束。在任何情况下,循环结束时都不会有十个对象。
第二种情况与w.r.t生命周期完全相同,但在堆上分配对象。这要慢得多,但是当您一直删除对象时,生命周期是相同的。在这种情况下,我建议使用std::unique_ptr
,因为它也是异常安全的,并且可以省去手动内存管理。当操作部件抛出异常时,你的代码有内存泄漏。
答案 2 :(得分:0)
方法1将在堆栈上分配员工对象,这肯定比使用动态内存分配器(堆)更快。在每次迭代时,employee对象都将超出范围,因此每次都会调用其析构函数。这对堆栈来说是好事,它会自动被垃圾收集&#39;离开范围时(见Is a destructor called when an object goes out of scope?)。