OPs 代码中的错误:
std::vector<Pet*> newVector {Cat(), Dog()};
Cat() 创建Cat 的临时实例。类型为Cat(或Cat&)。
std::vector<Pet*> 的元素类型是 Pet*,这是不兼容的。应用地址运算符 (&Cat()) 会使事情变得更糟。虽然现在类型会匹配(如果Cat 派生自Pet,则可以将Cat* 分配给Pet*),Cat() 会创建一个 临时 实例。它没有提供足够的生命周期,因为它会在表达式结束时自动销毁,这会在 std::vector 中留下一个悬空指针。
要解决这个问题,可以使用new:
std::vector<Pet*> newVector {new Cat(), new Dog()};
大肠杆菌上的 MCVE:
#include <iostream>
#include <memory>
#include <vector>
struct Pet {
virtual ~Pet() = default;
virtual const char* what() const = 0;
};
struct Cat: public Pet {
virtual const char* what() const override { return "cat"; }
};
struct Dog: public Pet {
virtual const char* what() const override { return "dog"; }
};
std::vector<Pet*> make_pets()
{
std::vector<std::unique_ptr<Pet>> vec{ new Cat(), new Dog() };
return vec;
}
int main()
{
std::vector<std::unique_ptr<Pet>> pets = make_pets();
std::cout << "Pets:\n";
for (const Pet *pPet : pets) std::cout << pPet->what() << '\n';
for (const Pet *pPet : pets) delete pPet;
}
输出:
Pets:
cat
dog
Live Demo on coliru
使用new 创建实例会导致必须使用delete 显式销毁这些实例。只是清除 std::vector<Pet*> pets 会导致实例未被删除并丢失——内存泄漏。
std::unique_ptr(由@user4581301 推荐)的用法有点棘手。因为std::unique_ptr 的实例是唯一拥有/持有指针的实例,所以它可能不会被复制或分配,而只是移动。经过一番摆弄,我得到了一个关于 coliru 的 mcve:
#include <iostream>
#include <memory>
#include <vector>
struct Pet {
virtual ~Pet() = default;
virtual const char* what() const = 0;
};
struct Cat: public Pet {
virtual const char* what() const override { return "cat"; }
};
struct Dog: public Pet {
virtual const char* what() const override { return "dog"; }
};
std::vector<std::unique_ptr<Pet>> make_pets()
{
std::vector<std::unique_ptr<Pet>> vec;
vec.emplace_back(std::make_unique<Cat>());
vec.emplace_back(std::make_unique<Dog>());
return vec;
}
int main()
{
std::vector<std::unique_ptr<Pet>> pets = make_pets();
std::cout << "Pets:\n";
for (const std::unique_ptr<Pet> &pPet : pets) std::cout << pPet->what() << '\n';
}
输出:
Pets:
cat
dog
Live Demo on coliru
在这种情况下,Pet 实例的销毁不是问题。 std::unique_ptr<Pet> 允许指针本身被删除后立即删除。