C++ shared_ptr拷贝与移动操作规则是什么

来源:站长联盟作者:乙爱丽丝头衔:网络博主
导读:本期聚焦于小伙伴创作的《C++ shared_ptr拷贝与移动操作规则是什么》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++ shared_ptr拷贝与移动操作规则是什么》有用,将其分享出去将是对创作者最好的鼓励。

在C++标准库的智能指针体系中,shared_ptr通过引用计数实现多个指针共享同一个堆对象的管理,其拷贝和移动操作的行为和普通原生指针、自定义对象都有明显差异,正确理解这些规则是合理使用shared_ptr的基础。

C++ shared_ptr拷贝与移动操作规则是什么

shared_ptr拷贝操作规则

当执行shared_ptr的拷贝构造或者拷贝赋值时,新生成的shared_ptr会和原shared_ptr共享被管理的对象,同时被管理对象的引用计数会增加1。拷贝操作不会重新分配被管理的对象内存,只是新增了一个指向该对象的智能指针实例。

拷贝构造示例

下面通过代码展示shared_ptr拷贝构造的行为:

#include <iostream>
#include <memory>

int main() {
    // 创建shared_ptr,管理一个int对象,此时引用计数为1
    std::shared_ptr<int> ptr1(new int(10));
    std::cout << "ptr1引用计数: " << ptr1.use_count() << std::endl;

    // 拷贝构造ptr2,ptr1和ptr2共享对象,引用计数加1
    std::shared_ptr<int> ptr2(ptr1);
    std::cout << "拷贝后ptr1引用计数: " << ptr1.use_count() << std::endl;
    std::cout << "拷贝后ptr2引用计数: " << ptr2.use_count() << std::endl;

    // 拷贝赋值,ptr3也会共享对象,引用计数再加1
    std::shared_ptr<int> ptr3;
    ptr3 = ptr2;
    std::cout << "拷贝赋值后引用计数: " << ptr1.use_count() << std::endl;

    // 三个指针指向的对象值相同
    std::cout << "*ptr1: " << *ptr1 << ", *ptr2: " << *ptr2 << ", *ptr3: " << *ptr3 << std::endl;
    return 0;
}

上述代码执行后,初始ptr1的引用计数为1,拷贝构造ptr2后引用计数变为2,拷贝赋值ptr3后引用计数变为3,三个指针解引用得到的值都是10,说明它们指向同一个对象。

拷贝操作的注意事项

  • 只要还有任意一个shared_ptr持有对象的所有权,对象就不会被释放,只有当所有shared_ptr都被销毁或者重置时,引用计数降为0,被管理对象才会被删除。
  • 拷贝操作是浅拷贝,不会复制被管理的对象本身,仅复制智能指针的控制块引用。
  • 不要将同一个原生指针多次用来初始化不同的shared_ptr,这会导致引用计数错误,引发重复释放的问题。

shared_ptr移动操作规则

shared_ptr的移动构造和移动赋值属于资源所有权的转移操作,移动后原shared_ptr会变为空指针,不再持有被管理对象的所有权,被管理对象的引用计数不会增加。

移动构造示例

通过代码展示移动操作的行为:

#include <iostream>
#include <memory>

int main() {
    // 创建shared_ptr,引用计数为1
    std::shared_ptr<int> ptr1(new int(20));
    std::cout << "移动前ptr1引用计数: " << ptr1.use_count() << std::endl;
    std::cout << "移动前ptr1是否为空: " << (ptr1 ? "否" : "是") << std::endl;

    // 移动构造ptr2,所有权从ptr1转移到ptr2
    std::shared_ptr<int> ptr2(std::move(ptr1));
    std::cout << "移动后ptr1引用计数: " << ptr1.use_count() << std::endl;
    std::cout << "移动后ptr1是否为空: " << (ptr1 ? "否" : "是") << std::endl;
    std::cout << "移动后ptr2引用计数: " << ptr2.use_count() << std::endl;

    // 移动赋值
    std::shared_ptr<int> ptr3;
    ptr3 = std::move(ptr2);
    std::cout << "移动赋值后ptr2是否为空: " << (ptr2 ? "否" : "是") << std::endl;
    std::cout << "移动赋值后ptr3引用计数: " << ptr3.use_count() << std::endl;
    return 0;
}

执行上述代码可以看到,移动操作后原shared_ptr变为空,引用计数始终为1,因为移动只是转移所有权,没有新增持有者。

移动操作的适用场景

  • 当需要将shared_ptr作为返回值从函数中返回时,编译器通常会自动触发移动操作,避免不必要的引用计数增减,提升性能。
  • 当明确不再需要使用原shared_ptr时,可以使用移动操作转移所有权,减少引用计数的维护开销。
  • 移动操作不会改变被管理对象的生命周期,只是改变所有权的持有者。

拷贝与移动操作的核心差异对比

为了更清晰区分两种操作,我们将核心差异整理为如下表格:

对比项拷贝操作移动操作
引用计数变化增加1不变
原shared_ptr状态仍然持有对象所有权变为空指针,失去所有权
对象共享情况多个shared_ptr共享同一对象仅转移后的shared_ptr持有对象
性能开销需要修改引用计数,有一定开销仅转移控制块指针,开销更低

常见使用误区

误区1:认为移动shared_ptr会复制被管理的对象,实际上移动只转移所有权,对象本身不会被复制。
误区2:对shared_ptr执行拷贝后,修改其中一个指针指向的对象,其他指针指向的对象也会被修改,因为共享的是同一个对象。

在实际开发中,需要根据是否需要共享对象所有权来选择使用拷贝还是移动操作,合理运用这两种操作可以让内存管理更安全高效。

shared_ptr拷贝构造移动构造引用计数智能指针修改时间:2026-06-23 18:57:37

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。