【问题标题】:How to correctly transfer the ownership of a shared_ptr?如何正确转移 shared_ptr 的所有权?
【发布时间】:2024-03-09 03:10:02
【问题描述】:

我有以下代码片段:

// code snipet one:
#include <memory> 
#include <iostream> 
#include <queue>

struct A {
    uint32_t val0 = 0xff;

    ~A() {
        std::cout << "item gets freed" << std::endl;
    }
};

typedef std::shared_ptr<A> A_PTR;

int main() 
{ 
    std::queue<A_PTR> Q;
    Q.push(std::make_shared<A>());
    auto && temp_PTR = Q.front();
    std::cout << "first use count = " << temp_PTR.use_count() << std::endl;
    Q.pop();
    std::cout << "second use count = " << temp_PTR.use_count() <<std::endl;
    return 0;
}

运行后得到如下结果:

first use count = 1                                                                                                                         
item gets freed 
second use count = 0

Q1:有谁能解释一下main函数第三行调用后的temp_PTR是什么类型的吗?

如果我将该行更改为

A_PTR && temp_PTR = Q.front();

编译器抱怨

main.cpp: In function 'int main()':
main.cpp:26:32: error: cannot bind '__gnu_cxx::__alloc_traits > >::value_type {aka std::shared_ptr}' lvalue to 'A_PTR&& {aka std::shared_ptr&&}'
     A_PTR && temp_PTR = Q.front();

Q2:我记得函数的返回值应该是一个r值,但是编译器似乎在这里告诉我:“嘿,Queue.front()的返回值是一个左值”,为什么会在这里?

【问题讨论】:

  • “因为这是性能损失” - 你的说法有任何衡量标准吗?
  • 至于你的第二个问题,没有一个函数应该返回的类型,有时你想按值返回,有时你想通过 const 引用返回,有时通过非 const 引用返回。在 this one 之类的网站上查找您不确定的功能的文档,了解它的详细功能。
  • “我认为下面的代码应该可以工作”,你尝试的时候发生了什么?
  • 有效,正确打印shared_ptr个数,析构函数的cout信息在程序末尾
  • 那么您为什么需要其他解决方案?您是否担心std::move 解决方案会太慢?如果是这种情况,我建议您测量它并查看它需要多长时间,但我几乎可以保证,如果您的程序运行缓慢,这不是因为您复制或移动了您的 shared_ptr

标签: c++11 shared-ptr rvalue-reference move-constructor move-assignment-operator


【解决方案1】:

对于第二季度,我只是检查了 C++ 文档,Queue.front() 的返回值是引用,这意味着它返回一个左值

reference& front();
const_reference& front() const;

对于第三季度,它适用于A_PTR temp_PTR = std::move(Q.front());,这是我想要的。

【讨论】: