C++ C++;使_共享调用析构函数两次

C++ C++;使_共享调用析构函数两次,c++,shared-ptr,C++,Shared Ptr,我有一些让我困惑的代码。我一直在学习共享指针,并在youtube上跟随一个指南。我正在使用make_shared构建我的狗,并将共享指针分配给p class Dog { private: std::string name; public: Dog(std::string _name): name(_name) { std::cout << "Creating dog wit

我有一些让我困惑的代码。我一直在学习共享指针,并在youtube上跟随一个指南。我正在使用make_shared构建我的狗,并将共享指针分配给p

class Dog
{
    private:
        std::string name;
    public:
        Dog(std::string _name):
            name(_name)
        {
            std::cout << "Creating dog with name " << name << std::endl;
        }

        ~Dog() { std::cout << "Destroying dog!" << std::endl; }

        void bark()
        {
            std::cout << name << " barks like a Dog! Woof!" << std::endl;
        }
};

std::shared_ptr<Dog> foo()
{
    std::cout << "Entering foo" << std::endl;
    std::shared_ptr<Dog> p = std::make_shared<Dog>("Tank"); //will be deleted when freed off stack

    std::cout << "Dog use count = " << p.use_count() << std::endl;

    std::shared_ptr<Dog> p2 = p;

    std::cout << "Dog use count = " << p.use_count() << std::endl;

    std::cout << "Returning first pointer from foo!" << std::endl;
    return p;
}
int main()
{
    std::shared_ptr<Dog> p = foo();

    std::cout << "Dog use count = " << p.use_count() << std::endl;

    return 0;
}
但是,以下是我的输出:

Entering foo
Creating dog with name Tank
Destroying dog!
Destroying dog!
Dog use count = 1
Dog use count = 2
Returning first pointer from foo!

有人能解释一下构造然后双重破坏的逻辑吗?

我想我已经弄明白了

我试着在centos上用

g++ shared_ptr.cpp
但是编译器抱怨说,共享的ptr不是std的一部分。改为

g++ -std=c++11 shared_ptr.cpp
使编译成功,我看到了预期的行为(没有双重破坏)

仅指定了我的mac的makefile

g++ shared_ptr.cpp
我在mac上检查了我的默认c标准,它被设置为199711L(1997ish)。尽管这不是c++11,但它似乎能够编译,尽管其行为显然很奇怪


在centOS上,默认std也是199711L,但编译失败。听起来这是一种未定义的行为,非常危险

您应该注意哪个实例正在被破坏。在调试器中逐步查找。您可能在此代码中创建了一个意外副本。。您使用的编译器和版本是什么?您是否启用了优化?提示:接受字符串参数为
const std::string&
,以避免无休止的无意义复制。您应该显示调用
foo
的代码。还要注意,
Dog
类具有隐式复制构造函数和赋值运算符。@tadman在本例中,该建议是错误的,因为它意味着至少需要进行一次复制,即从参数复制到成员。要最小化副本,请按值接受参数,然后将其移动到成员中。
g++ shared_ptr.cpp