【问题标题】:Why does make_shared destroy rvalue-references?为什么 make_shared 会破坏右值引用?
【发布时间】:2019-12-11 19:47:45
【问题描述】:

我试图了解我应该如何有效地使用智能指针,我很好奇它们如何与右值引用一起工作。为什么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 资源实际上并未移动资源。

【问题讨论】:

  • std::move 只是对右值引用进行强制转换,什么也不移动。目标变量将保持有效状态,因此将调用析构函数
  • 您的移动构造函数/移动赋值运算符在哪里?请注意,std::move 只是 强制转换 到右值引用。它不会自己做任何事情

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


【解决方案1】:
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

我统计了对析构函数的 2 次调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多