我有以下代码,其中未使用 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/