0

I'm trying to understand how I should use smart pointers efficiently, and I got curious about how they work together with rvalue references. How come std::make_shared (and presumably make_unique as well) uses copy semantics and not move semantics?

Here's a gtest test that showcases what I'm trying to say

#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
}

The second EXPECT_EQ fails, which hints to the moved b resource doesn't actually move the resource.

Asger Gitz
  • 31
  • 4
  • 2
    std::move just make a cast to rvalue reference and move nothing. There targeted variable will be left in valid state, so the destructor will be called – Roout Aug 03 '19 at 14:15
  • See also: https://stackoverflow.com/a/11148420/4658169 – CuriouslyRecurringThoughts Aug 03 '19 at 14:17
  • 1
    Where is your move constructor/move assignment operator? And note that `std::move` is *nothing but a cast* to rvalue reference. It doesn't do *anything* on its own. – Jesper Juhl Aug 03 '19 at 14:19

1 Answers1

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

In 1) you create a MoveSemanticsTest1.

In 2) you create a MoveSemanticsTest1 by move construction an give it to a shared_ptr. b is in a "moved from" state, but still here.

In 3) you destroy the shared_ptr => it destroy its MoveSemanticsTest1

In 4) you destroy the MoveSemanticsTest1 b.

I count 2 call to the destructor.

Martin Morterol
  • 2,560
  • 1
  • 10
  • 15