为什么make_shared销毁右值引用?

时间:2019-08-03 14:08:33

标签: c++ smart-pointers move-semantics

我试图了解如何有效使用智能指针,并且对它们如何与右值引用一起使用感到好奇。 std::make_shared(也可能还有make_unique)如何使用复制语义而不移动语义?

这是一项gtest测试,展示了我想说的话

#include <memory>
int dtor_calls = 0;
struct MoveSemanticsTest1 {
    int data;
    ~MoveSemanticsTest1() { dtor_calls++; }
};

void reset_move_dtor_calls() {
    dtor_calls = 0;
}

TEST(MoveSemanticsSanityTest1, SanityTests) {
    reset_move_dtor_calls();
    {
        MoveSemanticsTest1 a = MoveSemanticsTest1();
    }
    EXPECT_EQ(1, dtor_calls); // <-- This passes, makes sense
    reset_move_dtor_calls();
    {
        MoveSemanticsTest1 b = {3};
        auto a = std::make_shared<MoveSemanticsTest1>(std::move(b));
    }
    EXPECT_EQ(1, dtor_calls); // <-- This fails, why?
    reset_move_dtor_calls();
    {
        MoveSemanticsTest1 b = {3};
        auto a = std::make_shared<MoveSemanticsTest1>(b);
    }
    EXPECT_EQ(2, dtor_calls); // <-- This passes, makes sense because of the copying
}

第二个EXPECT_EQ失败,这表明移动的b资源实际上并未移动资源。

1 个答案:

答案 0 :(得分:2)

reset_move_dtor_calls();
{
    MoveSemanticsTest1 b = {3};  //1 
    auto a = std::make_shared<MoveSemanticsTest1>(std::move(b));  //2
    //3
    //4
}

在1)中,您创建了一个MoveSemanticsTest1

在2)中,您通过移动构造来创建MoveSemanticsTest1并将其赋予shared_ptrb处于“已移出”状态,但仍在这里。

在3)中,您破坏了shared_ptr =>它破坏了其MoveSemanticsTest1

在4)中,您摧毁了MoveSemanticsTest1 b

我算了两次对析构函数的调用。