2

I have this sample code below. I know little bit about RVO (return value optimization) and how copy constructor and assignment operator are skipped during the optimization and return of the value is placed directly on the memory on the left. So if shared pointer does the RVO how does the shared pointer know when to increase its counter? Because for some reason I thought shared pointer class would know when to increase counter based on the number copies or assignment it made.

#include <iostream>
#include <memory>
using namespace std;
class A{
public:
    A(){}
    A(const A& other){ std::cout << " Copy Constructor " << std::endl; }
    A& operator=(const A&other){
        std::cout << "Assingment operator " <<  std::endl;        
        return *this;
    }    
    ~A(){
        std::cout << "~A" <<  std::endl;
    } 
};

std::shared_ptr<A> give_me_A(){
    std::shared_ptr<A> sp(new A);
    return sp;
}

void pass_shared_ptr_by_val(std::shared_ptr<A> sp){

    std::cout << __func__ << ": count  sp = " << sp.use_count() << std::endl;
    std::shared_ptr<A> sp1 = sp;
    std::cout << __func__ << ": count  sp = " << sp.use_count() << std::endl;
    std::cout << __func__ << ": count sp1 = " << sp1.use_count() << std::endl;
}

void pass_shared_ptr_by_ref(std::shared_ptr<A>& sp){
    std::cout << __func__ << ": count  sp = " << sp.use_count() << std::endl;  
    std::shared_ptr<A> sp1 = sp;
    std::cout << __func__ << ": count  sp = " << sp.use_count() << std::endl;
    std::cout << __func__ << ": count sp1 = " << sp1.use_count() << std::endl;
}

int main(){

    {
        shared_ptr<A> sp3 = give_me_A();

        std::cout << "sp3 count = " << sp3.use_count() << std::endl;
        pass_shared_ptr_by_val(sp3);
        pass_shared_ptr_by_ref(sp3);
    }
return 0;
}

output:

sp3 count = 1


pass_shared_ptr_by_val: count sp = 2

pass_shared_ptr_by_val: count sp = 3

pass_shared_ptr_by_val: count sp1 = 3


pass_shared_ptr_by_ref: count sp = 1

pass_shared_ptr_by_ref: count sp = 2

pass_shared_ptr_by_ref: count sp1 = 2

~A

solti
  • 4,339
  • 3
  • 31
  • 51
  • 6
    If RVO is carried out then the shared pointer doesn't need to increment the reference count, because the copy is not carried out. I'm not sure what your question is. What output would you expect? – TartanLlama Jul 04 '16 at 14:45
  • @TartanLlama I thought RVO happens in pass by value as well .. hence copy constructor does not gets called .. but I was wrong... when passed by value copy constructor does gets called hence the counter increases. I think my doubt is clear now – solti Jul 04 '16 at 15:11

1 Answers1

8

If there is no copy, nothing needs to be counted.

If RVO is in play no copy is made, so why would the ref-count need to be increased? There is no extra object to destroy and decrement the ref-count.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
  • so in give_me_A function RVO does not happen? – solti Jul 04 '16 at 14:47
  • @solti It does (or it could). The ref count doesn't need to be touched because there's no copy. – TartanLlama Jul 04 '16 at 14:48
  • @Jesper Juhl and what about pass_shared_ptr_by_val .. here counter gets increased – solti Jul 04 '16 at 14:50
  • 3
    *If* a copy is made the ref-count will increase. If RVO is used, no copy is made and the ref-count doesn't increase. Simple as that. – Jesper Juhl Jul 04 '16 at 14:51
  • @JesperJuhl So ok My manin question is inside pass_shared_ptr_by_val the counter gets increased ... so it means here copy is made right? But I read some where RVO is used also inside pass by val .. is it not? – solti Jul 04 '16 at 14:54
  • 1
    You can read the rules about when RVO *may* happen here: http://en.cppreference.com/w/cpp/language/copy_elision Note that the compiler is not *required* to do RVO even if it can (changes somewhat in C++17). – Jesper Juhl Jul 04 '16 at 15:01