首页 > 编程语言 >C++中移动语义和拷贝语义的区别及智能指针

C++中移动语义和拷贝语义的区别及智能指针

时间:2024-11-22 21:43:52浏览次数:3  
标签:std p1 对象 语义 C++ shared 拷贝 include ptr

一、C++中移动语义和拷贝语义的区别

区别

  • 拷贝语义:在赋值或函数参数传递等操作时,会创建对象的一个完整副本。这意味着会分配新的内存空间,把原对象的数据复制到新内存中。如果对象数据量很大,复制操作会消耗较多资源(如时间、内存)。
  • 移动语义:是C++ 11引入的概念,用于优化对象资源所有权的转移。它不是复制数据,而是将资源的所有权从一个对象转移到另一个对象,避免了不必要的数据复制,特别是对于那些管理资源(如堆内存、文件句柄等)的对象,能大大提高性能。

#include <iostream>
#include <vector>
// 拷贝语义示例函数
void func_copy(std::vector<int> v) {
// 函数内部使用副本,不会影响原对象
std::cout << "拷贝语义函数内vector大小:" << v.size() << std::endl;
}
// 移动语义示例函数
void func_move(std::vector<int> &&v) {
// 函数接收右值引用,原对象资源被转移过来
std::cout << "移动语义函数内vector大小:" << v.size() << std::endl;
}
int main() {
std::vector<int> my_vector(1000);
// 拷贝语义,调用函数时会复制my_vector
func_copy(my_vector);
// 移动语义,调用函数时将my_vector资源所有权转移
func_move(std::move(my_vector));
// 此时my_vector已被移动,其状态在标准下是未指定的
// 通常其大小可能变为0,但不要依赖这种行为
std::cout << "main函数内vector大小:" << my_vector.size() << std::endl;
return 0;
}

在上述代码中, func_copy 函数体现了拷贝语义,在调用这个函数时会复制 my_vector 。 func_move 函数体现了移动语义,它接收右值引用,调用函数时原对象 my_vector 的资源所有权被转移,从而避免了复制大量数据的开销。注意在移动操作后,原对象的状态是未指定的。

二、智能指针

C++ 中的智能指针:

概念

智能指针是C++中的类模板,用于自动管理动态分配的内存。它的主要作用是防止内存泄漏,确保在适当的时候释放内存。

类型

1)shared_ptr:允许多个指针指向同一个对象,采用引用计数的方式来管理对象的生命周期。当引用计数为0时,对象会被自动销毁。

2)unique_ptr:独占所指向的对象,同一时间只能有一个unique_ptr指向一个对象,对象的所有权可以转移,但不能共享。

3)weak_ptr:是一种弱引用,主要用于配合shared_ptr解决循环引用的问题。它不控制对象的生命周期,只是观察对象是否存在。

#include <iostream>
#include <memory>
// shared_ptr示例
void sharedPtrExample() {
std::shared_ptr<int> p1 = std::make_shared<int>(10);
std::shared_ptr<int> p2 = p1;
std::cout << "p1引用计数: " << p1.use_count() << std::endl;
std::cout << "p2引用计数: " << p2.use_count() << std::endl;
}
// unique_ptr示例
void uniquePtrExample() {
std::unique_ptr<int> p1 = std::make_unique<int>(20);
// 转移所有权
std::unique_ptr<int> p2 = std::move(p1);
// 下面这行代码会出错,因为p1已经没有所有权
// std::cout << *p1 << std::endl;
if (p2) {
std::cout << *p2 << std::endl;
}
}
int main() {
sharedPtrExample();
uniquePtrExample();
return 0;
}

在这个代码中, sharedPtrExample 函数展示了 shared_ptr 的用法。 p1 和 p2 共享同一个对象,通过 use_count 函数可以查看引用计数。在 uniquePtrExample 函数里, unique_ptr 演示了对象所有权的独占性,通过 std::move 转移所有权后,原指针 p1 就不再拥有对象的控制权。

智能指针的类型:

1.std::shared_ptr

特点:采用引用计数机制。多个 shared_ptr 可以指向同一个对象,当所有指向该对象的 shared_ptr 引用计数为0时,对象才会被销毁。

#include <iostream>
#include <memory>
int main() {
// 创建一个shared_ptr,引用计数为1
std::shared_ptr<int> p1 = std::make_shared<int>(5);
std::shared_ptr<int> p2 = p1;
std::cout << "p1引用计数: " << p1.use_count() << std::endl;
// 手动释放p1,由于p2还指向对象,对象不会被销毁
p1.reset();
std::cout << "p2引用计数: " << p2.use_count() << std::endl;
// p2离开作用域,引用计数为0,对象被销毁
return 0;
}

2.std::unique_ptr

特点:独占所指向的对象,对象所有权唯一。不能进行复制,但可以转移所有权,这有效避免了资源的多重释放。

#include <iostream>
#include <memory>
int main() {
std::unique_ptr<int> p1 = std::make_unique<int>(10);
// 转移所有权,p2现在拥有对象,p1变为nullptr
std::unique_ptr<int> p2 = std::move(p1);
if (p1) {
std::cout << *p1 << std::endl;
}
if (p2) {
std::cout << *p2 << std::endl;
}
// p2离开作用域,对象被销毁
return 0;
}

3.std::weak_ptr

特点:是一种弱引用,不会增加对象的引用计数。主要用于解决 shared_ptr 循环引用的问题,它可以观察 shared_ptr 管理的对象是否存在。

#include <iostream>
#include <memory>
int main() {
std::shared_ptr<int> sp = std::make_shared<int>(20);
std::weak_ptr<int> wp(sp);
// 通过lock函数获取shared_ptr
if (auto shared_sp = wp.lock()) {
std::cout << "对象存在,值为: " << *shared_sp << std::endl;
} else {
std::cout << "对象不存在" << std::endl;
}
sp.reset();
if (auto shared_sp = wp.lock()) {
std::cout << "对象存在,值为: " << *shared_sp << std::endl;
} else {
std::cout << "对象不存在" << std::endl;
}
return 0;
}

标签:std,p1,对象,语义,C++,shared,拷贝,include,ptr
From: https://blog.csdn.net/2401_88249494/article/details/143983572

相关文章

  • C++ 模板元编程的深度探索与实践
    C++模板元编程是一种强大而又复杂的编程技术,它允许在编译期进行计算和代码生成。模板元编程的核心是模板的特化和递归。通过模板特化,可以针对不同的类型或条件生成特定的代码。例如,定义一个模板函数来计算一个数的阶乘:template<intN>structFactorial{staticconst......
  • C++ 跨平台开发的挑战与应对策略
    在当今多元化的操作系统环境下,C++跨平台开发成为许多软件项目的必然需求。然而,这一过程面临着诸多挑战。不同操作系统的API差异是首要问题。例如,在Windows系统中,图形界面开发通常使用WinAPI,而在Linux系统中则有GTK+、Qt等不同的库可供选择。对于文件操作,Windows使......
  • C++ 模板编程的高级应用与技巧
    C++模板是一种强大的泛型编程工具,它允许编写与类型无关的代码,极大地提高了代码的通用性和复用性。函数模板可以根据不同的参数类型生成相应的函数实例。例如,编写一个通用的排序函数模板,可以对不同类型的数组进行排序:template<typenameT>voidbubbleSort(Tarr[],intsize......
  • 根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles
    文章目录1旋转矩阵转换为欧拉角(EulerAngles)2欧拉角转换为旋转矩阵相机标定过程中,我们会得到一个3x3的旋转矩阵,下面是我们把旋转矩阵与欧拉角之间的相互转换:1旋转矩阵转换为欧拉角(EulerAngles)1、旋转矩阵是一个3x3的矩阵,如下:R=(r11r12r13r21r22r......
  • 【C++】绘制内存管理的地图
    生活是属于每个人自己的感受,不属于任何人的看法。前言 这是我自己学习C++的第二篇博客总结。后期我会继续把C++学习笔记开源至博客上。 上一期笔记是关于C++的类与对象础知识,没看的同学可以过去看看: 【C++】面向对象编程的艺术之旅-CSDN博客https://blog.csdn.net/......
  • 括号配对 C++题解
    括号配对内存限制:512MiB时间限制:1000ms标准输入输出题目类型:传统评测方式:文本比较题目描述Hecy又接了个新任务:BE处理。BE中有一类被称为GBE。以下是GBE的定义:空表达式是GBE如果表达式 A 是GBE,则 [A] 与 (A) 都是GBE如果 A 与 B 都是GBE,那么......
  • 回文质数 C++题解
    回文质数内存限制:64MiB时间限制:1000ms标准输入输出题目类型:传统评测方式:文本比较题目描述因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以151号是回文质数。写一个程序来找出范围[a,b](5<=a<b<=100,000,000)间的所有回文质数;输入......
  • 【C++篇】深度解析 C++ List 容器:底层设计与实现揭秘
    文章目录须知......
  • C++:多态
    目录一、多态的概念二、多态的定义及实现1、多态的构成条件2、虚函数3、虚函数的重写3.1、协变:3.2、析构函数重写:4、override和final关键字5、重载、覆盖、隐藏三、抽象类1、接口继承2、实现继承 一、多态的概念顾名思义,多态就是多种形态,举个例子:比如说买......
  • 什么是 C++ 中的智能指针?有哪些类型的智能指针?
    智能指针的定义在C++中,智能指针是一种类模板,用于管理动态分配的内存。它的主要目的是自动管理内存的生命周期,避免手动释放内存时可能出现的错误,如内存泄漏(忘记释放内存)和悬空指针(访问已释放的内存)。智能指针通过重载*(解引用运算符)和->(成员访问运算符)等运算符,使得它在行为......