C++ 向量为shared_ptr的类的析构函数导致错误
我有一个类动物,它是一些不同动物的基类,还有一个类畜群,它将共享的prt存储在一个载体中。我不熟悉智能指针,但为了处理继承,我不得不在代码中使用它们。它似乎工作得很好,但在我的代码到达“Herd”的析构函数后,它抛出了一个错误。 怎么了C++ 向量为shared_ptr的类的析构函数导致错误,c++,oop,vector,smart-pointers,C++,Oop,Vector,Smart Pointers,我有一个类动物,它是一些不同动物的基类,还有一个类畜群,它将共享的prt存储在一个载体中。我不熟悉智能指针,但为了处理继承,我不得不在代码中使用它们。它似乎工作得很好,但在我的代码到达“Herd”的析构函数后,它抛出了一个错误。 怎么了 class Animal { public: Animal(string _sound) : sound(_sound) {} void give_sound() { cout << sound <
class Animal {
public:
Animal(string _sound) :
sound(_sound) {}
void give_sound() {
cout << sound << " ";
}
bool operator==(Animal arg) {
return (typeid(*this).name() == typeid(arg).name());
}
protected:
string sound;
};
class Dog : public Animal {
public:
Dog() : Animal("woof") {}
};
class Cat : public Animal {
public:
Cat() : Animal("meow") {}
};
class Cow : public Animal {
public:
Cow() : Animal("moo") {}
};
class Herd {
public:
Herd() {}
~Herd() {
vec.clear();
}
Herd operator+(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
return *this;
}
void operator+=(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
}
void make_noise() {
vector<shared_ptr<Animal>>::iterator v = vec.begin();
while (v != vec.end()) {
(*v)->give_sound();
v++;
}
cout << endl;
}
private:
vector<shared_ptr<Animal>> vec;
};
int main() {
Herd herd;
Dog d1, d2;
Cat c1, c2;
cout << "sound 1: " << endl;
herd.make_noise();
herd += &d1;
herd += &c1;
cout << "sound 2: " << endl;
herd.make_noise();
herd += &d2;
herd += &c2;
cout << "sound 3: " << endl;
herd.make_noise();
//herd = herd - &d1;
//herd = herd - &d2;
cout << "sound 4: " << endl;
herd.make_noise();
return 0;
}
类动物{
公众:
动物(弦声):
声音(_声音){}
void发出声音{
库特
这些对象具有自动存储持续时间。它们不应该通过拥有智能指针来管理
智能指针的用例是堆分配,例如:
herd += new Dog;
这些对象具有自动存储持续时间。它们不应该通过拥有智能指针来管理
智能指针的用例是堆分配,例如:
herd += new Dog;
您的问题是传递具有自动存储持续时间的变量地址。
见:
这就是代码中发生的情况:
创建具有自动存储持续时间的变量:
Dog d1
它将在超出范围后自动销毁(在您的情况下是主功能的末尾)
然后,将其地址传递给将该地址存储在SharedPtr中的函数:
Herd operator+(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
return *this;
}
并按以下方式分配对象:
std::shared_ptr<Dog> d1 = std::make_shared<Dog>();
std::shared_ptr d1=std::make_shared();
您的问题是通过自动存储持续时间传递变量的地址。
见:
这就是代码中发生的情况:
创建具有自动存储持续时间的变量:
Dog d1
它将在超出范围后自动销毁(在您的情况下是主功能的末尾)
然后,将其地址传递给将该地址存储在SharedPtr中的函数:
Herd operator+(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
return *this;
}
并按以下方式分配对象:
std::shared_ptr<Dog> d1 = std::make_shared<Dog>();
std::shared_ptr d1=std::make_shared();
怎么了
class Animal {
public:
Animal(string _sound) :
sound(_sound) {}
void give_sound() {
cout << sound << " ";
}
bool operator==(Animal arg) {
return (typeid(*this).name() == typeid(arg).name());
}
protected:
string sound;
};
class Dog : public Animal {
public:
Dog() : Animal("woof") {}
};
class Cat : public Animal {
public:
Cat() : Animal("meow") {}
};
class Cow : public Animal {
public:
Cow() : Animal("moo") {}
};
class Herd {
public:
Herd() {}
~Herd() {
vec.clear();
}
Herd operator+(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
return *this;
}
void operator+=(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
}
void make_noise() {
vector<shared_ptr<Animal>>::iterator v = vec.begin();
while (v != vec.end()) {
(*v)->give_sound();
v++;
}
cout << endl;
}
private:
vector<shared_ptr<Animal>> vec;
};
int main() {
Herd herd;
Dog d1, d2;
Cat c1, c2;
cout << "sound 1: " << endl;
herd.make_noise();
herd += &d1;
herd += &c1;
cout << "sound 2: " << endl;
herd.make_noise();
herd += &d2;
herd += &c2;
cout << "sound 3: " << endl;
herd.make_noise();
//herd = herd - &d1;
//herd = herd - &d2;
cout << "sound 4: " << endl;
herd.make_noise();
return 0;
}
在此代码中,您试图使用堆栈分配对象创建shared_ptr
。这会导致双重删除此对象,第一次删除发生在堆栈对象超出范围时。第二次删除发生在shared_ptr
析构函数中的delete
运算符中。第二次删除无效,程序崩溃
Herd operator+(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
return *this;
}
void operator+=(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
}
畜群操作员+(动物*arg){
共享_ptr ptr(arg);
向量推回(ptr);
归还*这个;
}
无效运算符+=(动物*参数){
共享_ptr ptr(arg);
向量推回(ptr);
}
怎么了
class Animal {
public:
Animal(string _sound) :
sound(_sound) {}
void give_sound() {
cout << sound << " ";
}
bool operator==(Animal arg) {
return (typeid(*this).name() == typeid(arg).name());
}
protected:
string sound;
};
class Dog : public Animal {
public:
Dog() : Animal("woof") {}
};
class Cat : public Animal {
public:
Cat() : Animal("meow") {}
};
class Cow : public Animal {
public:
Cow() : Animal("moo") {}
};
class Herd {
public:
Herd() {}
~Herd() {
vec.clear();
}
Herd operator+(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
return *this;
}
void operator+=(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
}
void make_noise() {
vector<shared_ptr<Animal>>::iterator v = vec.begin();
while (v != vec.end()) {
(*v)->give_sound();
v++;
}
cout << endl;
}
private:
vector<shared_ptr<Animal>> vec;
};
int main() {
Herd herd;
Dog d1, d2;
Cat c1, c2;
cout << "sound 1: " << endl;
herd.make_noise();
herd += &d1;
herd += &c1;
cout << "sound 2: " << endl;
herd.make_noise();
herd += &d2;
herd += &c2;
cout << "sound 3: " << endl;
herd.make_noise();
//herd = herd - &d1;
//herd = herd - &d2;
cout << "sound 4: " << endl;
herd.make_noise();
return 0;
}
在此代码中,您试图使用堆栈分配对象创建shared_ptr
。这会导致双重删除此对象,第一次删除发生在堆栈对象超出范围时。第二次删除发生在shared_ptr
析构函数中的delete
运算符中。第二次删除无效,程序崩溃
Herd operator+(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
return *this;
}
void operator+=(Animal *arg) {
shared_ptr<Animal> ptr(arg);
vec.push_back(ptr);
}
畜群操作员+(动物*arg){
共享_ptr ptr(arg);
向量推回(ptr);
归还*这个;
}
无效运算符+=(动物*参数){
共享_ptr ptr(arg);
向量推回(ptr);
}
我可以看到两个明显的问题
第一,正如其他人所提到的,是shared\u ptr
假设它管理的对象是动态创建的(使用operatornew
),所以使用operatordelete
(除非在构造共享\u ptr
时提供了自定义删除程序,否则您的代码不会这样做。将运算符删除应用于具有自动
存储持续时间的对象会导致未定义的行为
第二个问题——在解决第一个问题后,您最终会遇到这个问题——是类动物没有虚拟析构函数。即使使用操作符新建创建对象,操作符删除也会导致从动物派生的实际类型的对象出现未定义的行为e> (即,如果实际对象的类型为Cat
,Dog
等)。我可以看到两个明显的问题
第一,正如其他人所提到的,是shared\u ptr
假设它管理的对象是动态创建的(使用operatornew
),所以使用operatordelete
(除非在构造共享\u ptr
时提供了自定义删除程序,否则您的代码不会这样做。将运算符删除应用于具有自动
存储持续时间的对象会导致未定义的行为
第二个问题——在解决第一个问题后,您最终会遇到这个问题——是类动物没有虚拟析构函数。即使使用操作符新建创建对象,操作符删除也会导致从动物派生的实际类型的对象出现未定义的行为e> (即,如果实际对象的类型为Cat
、Dog
等)。在问题中发布代码。@molbdnilo这里是“我不熟悉智能指针,但为了处理继承,我必须在代码中使用它们。”我有点困惑。智能指针显然在这里不起作用,因为对象是在堆栈上分配的。但是一个普通的哑指针应该可以很好地工作。你为什么认为你需要智能指针呢?在这里发布问题中的代码。@molbdnilo在这里“我不熟悉智能指针,但为了处理继承,我不得不在代码中使用它们。"我有点困惑。智能指针显然在这里不起作用,因为对象是在堆栈上分配的。但是一个普通的哑指针应该可以正常工作。为什么你认为你在这里需要智能指针?那么我应该如何声明它们呢?@IFeel3,你不需要。std::make_shared
使用动态存储创建一个对象你不需要声明d1、d2、c1、c2
没有声明动物对象,比如Dog*d=new Dog;
prefered?@IFeel3,这将创建一个具有动态st的对象