【问题标题】:How does shared_ptr increase counter when passed by value?shared_ptr 按值传递时如何增加计数器?
【发布时间】:2016-07-04 14:42:17
【问题描述】:

我在下面有这个示例代码。我对 RVO(返回值优化)以及如何在优化过程中跳过复制构造函数和赋值运算符以及将值的返回直接放在左侧的内存中了解一点。那么如果共享指针是 RVO,共享指针如何知道何时增加它的计数器呢?因为出于某种原因,我认为共享指针类会根据它所做的副本数或分配数知道何时增加计数器。

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

输出:

sp3 计数 = 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

【问题讨论】:

  • 如果执行RVO,则共享指针不需要增加引用计数,因为不执行复制。我不确定你的问题是什么。你期望什么输出?
  • @TartanLlama 我认为 RVO 也发生在按值传递中..因此不会调用复制构造函数..但我错了...当按值传递时复制构造函数会被调用,因此计数器增加。我想我的疑问现在很清楚了

标签: c++ shared-ptr smart-pointers rvo


【解决方案1】:

如果没有副本,则无需计算任何内容。

如果 RVO 正在运行,则没有复制,那么为什么需要增加引用计数?没有额外的对象来销毁和减少引用计数。

【讨论】:

  • 所以在 give_me_A 函数中 RVO 不会发生?
  • @solti 确实(或可以)。因为没有副本,所以不需要触及 ref 计数。
  • @Jesper Juhl 以及 pass_shared_ptr_by_val .. 这里计数器增加了
  • 如果复制了一份,引用计数将增加。如果使用 RVO,则不会进行复制,并且引用计数不会增加。就这么简单。
  • 您可以在此处阅读有关何时可能发生 RVO 的规则:en.cppreference.com/w/cpp/language/copy_elision 请注意,编译器不是必需来执行 RVO,即使它可以(在 C++17 中有所改变)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多