无法从引用创建共享指针

Fail to make a shared pointer from a reference

本文关键字:共享 指针 创建 引用      更新时间:2024-05-24

这里的主要问题是:我可以使用引用创建共享指针吗?

在下面的代码中,类AnimalList实现了一个容器,该容器保存指向派生自Animal的所有类型的共享指针向量。为了将项推送到容器中,类AnimalList有两种方法,一种允许引用,另一种接受共享指针。

显然,通过引用创建共享指针无法提供所需的结果。请参阅第 [5] 行处的分段错误。

我知道有人建议避免从引用中创建共享指针。但我不太明白为什么以这种方式通过引用创建共享指针会失败。如果这可能的话,正确的方法应该是什么?

#include <iostream>
#include <string>
#include <vector>
#include <memory>

class Animal {
private:
std::string type = "Animal";
public:
Animal() {}
virtual std::string get_type() { return type; }
};

class Bird : public Animal {
private:
std::string type = "Bird";
public:
Bird() {}
std::string get_type() { return type; }
};

class Mammal : public Animal {
private:
std::string type = "Mammal";
public:
Mammal() {}
std::string get_type() { return type; }
};

class AnimalList {
public:
std::vector<std::shared_ptr<Animal> > list;          // [1]
void push(Animal& ref) {                             // [2]  
list.push_back(std::make_shared<Animal>(ref));
}
void push(std::shared_ptr<Animal> shared_ptr) {
list.push_back(shared_ptr);
}
};
int main() {
Bird magpie;
std::shared_ptr<Mammal> dog_ptr (new Mammal());
AnimalList list;
list.push(magpie);       // [3]
list.push(dog_ptr);      // [4]
//std::cout << std::dynamic_pointer_cast<Bird>(list.list[0])->get_type() << "n";    //[5] Segmentation fault
std::cout << std::dynamic_pointer_cast<Mammal>(list.list[1])->get_type() << "n";    //[6] Mammal
return 0;
}

如果你引用堆栈中的一个对象并从中创建一个共享指针,你告诉系统"嘿,我希望两个所有者控制它。这意味着有两件事会试图杀死物体,这是不行的。每个对象只能有一个所有者。如果你想要一个共享指针,则必须以没有其他人拥有它的方式构造对象。

您需要传递共享指针、创建副本或以其他方式动态创建对象。然后只有一个东西拥有对象并处理它的销毁。

给定std::make_shared<Animal>(ref),你正在创建一个指向Animalstd::shared_ptr,它是从ref复制构造的。然后动态强制转换失败,std::dynamic_pointer_cast<Bird>(list.list[0])返回空指针。

您需要从一开始就创建指向Birdstd::shared_ptr

例如
void push(Bird& ref) {                             // [2]  
list.push_back(std::make_shared<Bird>(ref));
}

顺便说一句:Animal的析构函数应该标记为virtual