Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 向量为shared_ptr的类的析构函数导致错误_C++_Oop_Vector_Smart Pointers - Fatal编程技术网

C++ 向量为shared_ptr的类的析构函数导致错误

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 <

我有一个类动物,它是一些不同动物的基类,还有一个类畜群,它将共享的prt存储在一个载体中。我不熟悉智能指针,但为了处理继承,我不得不在代码中使用它们。它似乎工作得很好,但在我的代码到达“Herd”的析构函数后,它抛出了一个错误。 怎么了

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
假设它管理的对象是动态创建的(使用operator
new
),所以使用operator
delete
(除非在构造
共享\u ptr
时提供了自定义删除程序,否则您的代码不会这样做。将运算符删除应用于具有
自动
存储持续时间的对象会导致未定义的行为


第二个问题——在解决第一个问题后,您最终会遇到这个问题——是类
动物
没有
虚拟
析构函数。即使使用操作符
新建
创建对象,操作符
删除
也会导致从
动物
派生的实际类型的对象出现未定义的行为e> (即,如果实际对象的类型为
Cat
Dog
等)。

我可以看到两个明显的问题

第一,正如其他人所提到的,是
shared\u ptr
假设它管理的对象是动态创建的(使用operator
new
),所以使用operator
delete
(除非在构造
共享\u ptr
时提供了自定义删除程序,否则您的代码不会这样做。将运算符删除应用于具有
自动
存储持续时间的对象会导致未定义的行为


第二个问题——在解决第一个问题后,您最终会遇到这个问题——是类
动物
没有
虚拟
析构函数。即使使用操作符
新建
创建对象,操作符
删除
也会导致从
动物
派生的实际类型的对象出现未定义的行为e> (即,如果实际对象的类型为
Cat
Dog
等)。

在问题中发布代码。@molbdnilo这里是“我不熟悉智能指针,但为了处理继承,我必须在代码中使用它们。”我有点困惑。智能指针显然在这里不起作用,因为对象是在堆栈上分配的。但是一个普通的哑指针应该可以很好地工作。你为什么认为你需要智能指针呢?在这里发布问题中的代码。@molbdnilo在这里“我不熟悉智能指针,但为了处理继承,我不得不在代码中使用它们。"我有点困惑。智能指针显然在这里不起作用,因为对象是在堆栈上分配的。但是一个普通的哑指针应该可以正常工作。为什么你认为你在这里需要智能指针?那么我应该如何声明它们呢?@IFeel3,你不需要。
std::make_shared
使用动态存储创建一个对象你不需要声明
d1、d2、c1、c2
没有声明动物对象,比如
Dog*d=new Dog;
prefered?@IFeel3,这将创建一个具有动态st的对象