为何对std::shared_ptr执行std::move后use_count反而增加?
你的问题核心在于缺少了<utility>头文件,导致std::move没有被正确识别,最终执行了复制构造而非移动构造,这才出现了引用计数不降反升的情况。
为什么会这样?
std::move是C++标准库中定义在<utility>头文件里的模板函数,它的作用是将左值转换为右值引用,从而触发移动语义。如果你的代码没有包含<utility>,编译器可能无法找到std::move的正确定义——在你使用的Apple LLVM 10.0.1这类旧版本编译器中,可能不会直接报错,而是将std::move(x)错误地处理为返回左值引用的恒等操作,相当于直接使用x本身。
这样一来,std::shared_ptr<Thing> y = std::move(x);这行代码就从移动构造变成了复制构造:
- 复制构造会增加引用计数,所以
x和y共享同一个对象,引用计数从1变成2。 - 这完全违背了你原本期望的“移动后原指针置空、引用计数保持1”的结果。
解决方案
只需要在代码开头添加<utility>头文件即可:
#include <cstdio> #include <memory> #include <utility> // 新增这一行 class Thing { public: Thing(int N) : value(N) {} int value; }; void print(const char* name, const std::shared_ptr<Thing>& sp) { // 建议改成const引用 printf("%s: { use_count=%i; }\n", name, (int)sp.use_count()); } int main(int argc, char** argv) { std::shared_ptr<Thing> x(new Thing(4711)); print("BEFORE x", x); std::shared_ptr<Thing> y = std::move(x); y->value = 4712; print(" AFTER x", x); print(" AFTER y", y); return 0; }
重新编译运行后,你会得到符合预期的输出:
BEFORE x: { use_count=1; } AFTER x: { use_count=0; } AFTER y: { use_count=1; }
额外建议
你的print函数不需要修改传入的shared_ptr,所以最好将参数改为const std::shared_ptr<Thing>& sp——这不仅更符合代码语义,还能避免意外修改,同时也不会影响引用计数(因为const引用不会触发复制)。
内容的提问来源于stack exchange,提问作者Frank-Rene Schäfer
相关产品推荐
相关产品推荐

