c++ - 析构函数被调用的次数超过预期

标签 c++ c++11

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

#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。我错过了什么?

最佳答案

Move 不会破坏对象,它只是将它们的状态标记为一次性。所以移动不会导致破坏(除非 vector 被推回重新分配!)

自动存储对象(例如,在函数中声明为局部对象)在其作用域结束时被销毁。这就是为什么您在最后得到所有这些析构函数的原因。

当 vector 被销毁时,它会销毁存储在其中的动物(它们不是熊或斑马,只是动物,因为您要求它们按值存储,这意味着 Bear-ness 被切掉了) .这是析构函数的另一个来源。

for (auto i:animals) 循环还会为 vector 中的每只动物创建一个拷贝,该拷贝将被销毁。还有更多的破坏性垃圾邮件。

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 行,我会注释掉第 2 行。

关于c++ - 析构函数被调用的次数超过预期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33307741/

相关文章:

c++ - 如何将所有对从一个 std::map 移动到另一个

c++ - C++11 中的线程

c++ - 为进程设置更高的优先级到 boost::asio 线程

c++ - 如何从作为模式给出的 std::string 中提取单词?

c++ - 我如何使用 CMake 将 opencv 简单地包含在我的项目中

c++ - 具有多个参数的 Map.emplace C++ 17

c++ - 另一个与设计相关的 C++ 问题

c++ - Qt:在QMap中找到最接近的QVector3D

c++ - 树删除节点

c++11 - 对于非空字符串,data() 是否保证等于 &front()?