maufcost
maufcost

Reputation: 169

Calling std::swap in shared pointers' values call a bunch of constructors and destructors

I have recently started learning move semantics and shared pointers, and I am having a lot of difficulty trying to understand it.

I am currently taking a course on these topics, but the instructor did not explain why these constructors and destructors are called when we swap the values contained in the pointers. The calls to swap in the shared pointer (as in b.swap(a)) and the std::swap(a, b) are not calling any constructors or destructor, while the call to std::swap(*a, *b) are calling a bunch of them.

The main code:

int main(int argc, char** argv){

    std::shared_ptr<strc> a = std::make_shared<strc>("one");
    std::shared_ptr<strc> b = std::make_shared<strc>("two");

    message("b.swap(a)"); // No constructors or destructors are called.
    b.swap(a);
    disp(a);
    disp(b);

    message("std::swap"); // A bunch of constructors and destructors are called.
    std::swap(*a, *b);
    disp(a);
    disp(b);

    message("std::swap"); // No constructor or destructors are called.
    std::swap(a, b);
    disp(a);
    disp(b);

    return 0;
}

The implemented class for "strc" is (I am just going to show the 'important' implementations in it for the sake of conciseness):

strc::strc(strc && o){
    msg("Move Constructor.");
    this->data = std::move(o.data);
    o.data = nullptr;
}

strc::~strc(){
    msg("Destructor.");
    delete [] data;
}

strc & strc::operator = (strc o){
    msg("Copy and Swap (=).");
    swap(o);
    return *this;
}

void strc::swap(strc & o){
    msg("Calling std::swap");
    std::swap(this->data, o.data);
}

This is what is being printed to the console (For me to understand more about what is happening and have a thorough understanding of move semantics and shared pointers).

Call to b.swap(a) one (1) two (1)

Call to std::swap(*a, *b) strc: Move Constructor. strc: Move Constructor. strc: Copy and Swap (=). strc: Calling std::swap strc: Destructor. strc: Move Constructor. strc: Copy and Swap (=). strc: Calling std::swap strc: Destructor. strc: Destructor. two (1) one (1)

Call to std::swap(a, b) one (1) two (1)

Why is that? Does it have to do with the move semantics? Shouldn't it be calling the standard swap function? I cannot understand the difference between these swap calls, and why one of them is calling all of these constructors and destructor.

Upvotes: 0

Views: 306

Answers (1)

3CxEZiVlQ
3CxEZiVlQ

Reputation: 38405

  1. b.swap(a) swaps pointers.
  2. std::swap(*a, *b) swaps contents of pointed objects.
  3. std::swap(a, b) swaps pointers again.

Move constructors are used in the case 2. It is what they are for.

Move constructors are used in the case 1 and 3 too, but you do not observe this since you did not modify std::shared_ptr constructors.

You can learn more here Should the Copy-and-Swap Idiom become the Copy-and-Move Idiom in C++11?

Upvotes: 1

Related Questions