析构函数的调用量超出预期 [英] Destructor being called more than expected

查看:84
本文介绍了析构函数的调用量超出预期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码,其中不使用new,但是调用了std :: move()。

I have the following code where new is not used, but std::move() is called.

#include <iostream>
#include <vector>
#include <utility>

class Animal {
public:
    Animal() { std::cout << "Animal()" << std::endl; };
    ~Animal() { std::cout << "~Animal()" << std::endl; };
    virtual void eat() { std::cout << "Animal is eating" << std::endl; };
};

class Bear : public Animal {
public:
    Bear() { std::cout << "Bear()" << std::endl; };
    ~Bear() { std::cout << "~Bear()" << std::endl; };
    void eat() { std::cout << "Bear is eating" << std::endl; };
};

class Zebra : public Animal {
public:
    Zebra() { std::cout << "Zebra()" << std::endl; };
    ~Zebra() { std::cout << "~Zebra()" << std::endl; };
    void eat() { std::cout << "Zebra is eating" << std::endl; };
};

int main()
{
    Bear bear;
    Zebra zebra;

    std::vector<Animal*> animalsp;
    animalsp.push_back(&bear);
    animalsp.push_back(&zebra);
    for (auto i : animalsp) {
        i->eat();
    }

    std::vector<Animal> animals;
    animals.push_back(std::move(bear));
    animals.push_back(std::move(zebra));
    for (auto i : animals) {
        i.eat();
    }

    return 0;
}

我得到以下输出:

Animal()
Bear()
Animal()
Zebra()
Bear is eating
Zebra is eating
~Animal()
Animal is eating
~Animal()
Animal is eating
~Animal()
~Animal()
~Animal()
~Zebra()
~Animal()
~Bear()
~Animal()

我希望对〜Animal()析构函数的调用更少。我还发现调用〜Animal()的时间是意外的。我本来希望 std :: move()调用可能触发此操作,但随后在函数调用的输出之前执行此操作。我在 ideone 和VS2015上获得了相同的输出。我缺少什么?

I would have expected fewer calls to the ~Animal() destructor. I also find the timing of the calls to ~Animal() to be unexpected. I would have expected the std::move() call to trigger this perhaps, but then to do so before the output of the function call. I get the same output on ideone and VS2015. What am I missing?

推荐答案

移动不会破坏对象,它只是将对象的状态标记为可抛弃。因此,此移动不会造成破坏(除非通过后推来重新分配向量!)

Move doesn't destroy objects, it just flags their state as being disposable. So the move doesn't cause a destroy (unless the vector is reallocated by the push back!)

自动存储对象(例如,在函数中声明为局部变量)是在其作用范围的尽头销毁。这就是为什么最后要拥有所有这些析构函数的原因。

Automatic storage objects (declared as locals in a function, say) are destroyed at the end of their scope. That is why you get all those destructors at the end.

当向量被销毁时,它会销毁存储在其中的动物(不是熊或斑马,只是动物) ,就像您要求按值存储它们一样,这意味着Bearness被切掉了)。这是析构函数的另一个来源。

When the vector is destroyed, it destroys the animals stored inside it (which are not Bears or Zebras, just animals, as you asked them to be stored by-value, and that means the Bear-ness got sliced off them). This is another source of destructors.

for(auto i:animals)的循环还会创建每个副本的副本。媒介中的动物,被破坏了。

The for (auto i:animals) loop also creates a copy of each animal in the vector, which is destroyed. Yet more destructor spam.

Animal()
Bear() // Bear bear; line
Animal()
Zebra() // Zebra zebra; line
Bear is eating
Zebra is eating // first loop
~Animal() // reallocation of vector during push_backs
Animal is eating // second loop body
~Animal() // first i copy destroyed in second loop
Animal is eating // second loop body
~Animal() // second i copy destroyed in second loop 
~Animal()
~Animal() // vector destroyed 
~Zebra()
~Animal() // zerbra destroyed
~Bear()
~Animal() // bear destroyed

如果某事物需要2行,我评论了第二行。

In the event that something takes 2 lines, I commented the 2nd line.

这篇关于析构函数的调用量超出预期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆