广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++11移动构造函数的使用
  • 581
分享到

C++11移动构造函数的使用

2024-04-02 19:04:59 581人浏览 八月长安
摘要

目录一、引言二、左值和右值三、深拷贝构造函数四、右值引用五、移动构造函数六、std::move()七、参考资料一、引言 移动构造函数是什么?先举个例子,你有一本书,你不想看,但我很想

一、引言

移动构造函数是什么?先举个例子,你有一本书,你不想看,但我很想看,那么我有哪些方法可以让我能看这本书?有两种做法,一种是你直接把书交给我,另一种是我去买一些稿纸来,然后照着你这本书一字一句抄到稿纸上。

显然,第二种方法很浪费时间,但这正是有些深拷贝构造函数的做法,而移动构造函数便能像第一种做法一样省时,第一种做法在 c++ 中叫做完美转发。

二、左值和右值

何为左值?能用取址符号 & 取出地址的皆为左值,剩下的都是右值。

而且,匿名变量一律属于右值。

int i = 1; // i 是左值,1 是右值

int GetZero {
    int zero = 0;
    return zero;
}
//j 是左值,GetZero() 是右值,因为返回值存在于寄存器中
int j = GetZero();

//s 是左值,string("no name") 是匿名变量,是右值
string s = string("no name");

三、深拷贝构造函数

用 g++ 编译器编译下列代码时记得加上参数 -fno-elide-constructors。

#include <iOStream>
#include <string>

using namespace std;

class Integer {
public:
    //参数为常量左值引用的深拷贝构造函数,不改变 source.ptr_ 的值
    Integer(const Integer& source)
      : ptr_(new int(*source.ptr_)) {
        cout << "Call Integer(const Integer& source)" << endl;
    }
    
    //参数为左值引用的深拷贝构造函数,转移堆内存资源所有权,改变 source.ptr_ 的值
    Integer(Integer& source)
      : ptr_(source.ptr_) {
        source.ptr_ = nullptr;
        cout << "Call Integer(Integer& source)" << endl;
    }
    
    Integer(int value)
      : ptr_(new int(value)) {
        cout << "Call Integer(int value)" << endl;
    }

    ~Integer() {
        cout << "Call ~Integer()" << endl;
        delete ptr_;
    }

    int GetValue(void) { return *ptr_; }

private:
    string name_;
    int* ptr_;
};

int
main(int arGC, char const* argv[]) {
    Integer a(Integer(100));
    int a_value = a.GetValue();
    cout << a_value << endl;
    cout << "-----------------" << endl;
    Integer temp(10000);
    Integer b(temp);
    int b_value = b.GetValue();
    cout << b_value << endl;
    cout << "-----------------" << endl;

    return 0;
}

运行结果如下。

Call Integer(int value)
Call Integer(const Integer& source)
Call ~Integer()
100
-----------------
Call Integer(int value)
Call Integer(Integer& source)
10000
-----------------
Call ~Integer()
Call ~Integer()
Call ~Integer()

在程序中,参数为常量左值引用的深拷贝构造函数的做法相当于引言中的第二种做法,“重买稿纸”相当于再申请一次堆内存资源,“重新抄写”相当于把匿名对象 Integer(100) 的资源拷贝到对象 a 这边;参数为左值引用的深拷贝构造函数的做法则相当于引言中的第一种做法,语句 ptr_(source.ptr_) 和 source.ptr_ = nullptr; 的作用相当于“我直接把书拿给你”。

由运行结果可以看出,当同时存在参数类型为常量左值引用和左值引用的深拷贝构造函数时,匿名对象 Integer(100) 只能选择前者,非匿名对象 temp 可以选择后者,这是因为常量左值引用可以接受左值、右值、常量左值、常量右值,而左值引用只能接受左值。因此,对于匿名变量,参数为任何类型左值引用的深拷贝构造函数都无法实现完美转发。还有一种办法——右值引用。

四、右值引用

右值引用也是引用的一种,参数类型为右值引用的函数只能接受右值参数,但不包括模板函数,参数类型为右值引用的模板函数不在本文讨论的范围内。

五、移动构造函数

移动构造函数是参数类型为右值引用的拷贝构造函数。

在“三”示例程序 Interger 类的定义中添加一个移动构造函数,其余保持原样。

//参数为左值引用的深拷贝构造函数,转移堆内存资源所有权,改变 source.ptr_ 的值
Integer(Integer& source)
  : ptr_(source.ptr_) {
    source.ptr_ = nullptr;
    cout << "Call Integer(Integer& source)" << endl;
}

//移动构造函数,与参数为左值引用的深拷贝构造函数基本一样
Integer(Integer&& source)
  : ptr_(source.ptr_) {
    source.ptr_ = nullptr;
    cout << "Call Integer(Integer&& source)" << endl;
}

Integer(int value)
  : ptr_(new int(value)) {
    cout << "Call Integer(int value)" << endl;
}

运行结果如下。

Call Integer(int value)
Call Integer(Integer&& source)
Call ~Integer()
100
-----------------
Call Integer(int value)
Call Integer(Integer& source)
10000
-----------------
Call ~Integer()
Call ~Integer()
Call ~Integer()

只有第二行跟先前不同,匿名对象 Integer(100) 也能通过移动构造函数实现完美转发。

大家可能会有疑问,上文提及到常量左值引用也可以接受右值,而右值引用也可以接受右值,那一个右值是否有可能会套入一个参数类型为常量左值引用的函数呢?答案是不会,一个右值要套入函数时,会优先选择套入参数类型为右值引用的函数。

可是仔细想想还是有点不满意,如果要让左值和右值的深拷贝都能实现完美转发,就需要写两个内容基本一样的拷贝构造函数,一个参数为(非常量)左值引用,一个参数为右值,那能不能只用一个函数就能实现左值、右值两者的深拷贝完美转发呢?答案就是强制类型转换,将左值强制强制转换为右值,再套入参数类型为右值引用的深拷贝构造函数。

六、std::move()

std::move() 能把左值强制转换为右值。

我们把语句 Integer b(temp); 改为 Integer b(std::move(temp)); 后,运行结果如下。

Call Integer(int value)
Call Integer(Integer&& source)
Call ~Integer()
100
-----------------
Call Integer(int value)
Call Integer(Integer&& source)
10000
-----------------
Call ~Integer()
Call ~Integer()
Call ~Integer()

从“10000”的上一行可以看出,std::move() 确实把左值 temp 转换为右值。

七、参考资料

《从4行代码看右值引用》 博客园用户“qicosmos(江南)” 著

到此这篇关于C++11 移动构造函数的使用的文章就介绍到这了,更多相关C++11 移动构造函数的使用内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++11移动构造函数的使用

本文链接: https://www.lsjlt.com/news/163671.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++11移动构造函数的使用
    目录一、引言二、左值和右值三、深拷贝构造函数四、右值引用五、移动构造函数六、std::move()七、参考资料一、引言 移动构造函数是什么?先举个例子,你有一本书,你不想看,但我很想...
    99+
    2022-11-13
  • C++11怎么移动构造函数通常
    这篇文章主要讲解了“C++11怎么移动构造函数通常”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++11怎么移动构造函数通常”吧!不会抛出异常的移动构造函数拷贝构造函数通常伴随着内存分配操...
    99+
    2023-06-19
  • C++11中移动构造函数案例代码
    目录1. 拷贝构造函数中的深拷贝问题2. C++移动构造函数(移动语义的具体实现)1. 拷贝构造函数中的深拷贝问题 在 C++ 98/03 标准中,如果想用其它对象初始化一个同类的新...
    99+
    2023-01-04
    C++11移动构造函数 C++11构造函数 C++构造函数
  • C++11继承的构造函数怎么使用
    本篇内容主要讲解“C++11继承的构造函数怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++11继承的构造函数怎么使用”吧!多重继承的情况上述方法在多重继承时仍然有效,除了一种情况:被...
    99+
    2023-06-19
  • C++11中委托构造函数如何使用
    这篇文章将为大家详细讲解有关C++11中委托构造函数如何使用,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。C++11之前的状况构造函数多了以后,几乎必然地会出现代码重复的情况,为了避免这种情...
    99+
    2023-06-19
  • C++移动构造函数和移动赋值的用法
    本篇内容介绍了“C++移动构造函数和移动赋值的用法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!移动构造函数首先看通常的拷贝构造函数:拷贝构...
    99+
    2023-06-19
  • C++赋值函数+移动赋值函数+移动构造函数详解
    目录左值引用和右值引用左值与右值左右值的切换左值引用:将左值绑定在引用上常量左值引用和非常量左值引用右值引用:将右值绑定在引用上常量右值引用和非常量右值引用移动构造函数赋值和移动赋值...
    99+
    2022-11-13
  • C++11中 constexpr构造函数的作用是什么
    这期内容当中小编将会给大家带来有关C++11中 constexpr构造函数的作用是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。聚合类聚合类(aggregate class)允许利用者直接访问其成员,...
    99+
    2023-06-19
  • C++11继承的构造函数举例分析
    本篇内容主要讲解“C++11继承的构造函数举例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++11继承的构造函数举例分析”吧!假设我们有下面的CRect类:由于今天的内容是讲构造函数的,...
    99+
    2023-06-19
  • 聊聊C++中右值引用和移动构造函数的使用
    目录一: 背景二: 右值引用1. 它到底解决了什么问题2. 右值引用是个什么样子三: 右值引用如何减少对象的创建1. 简要思路2. 一个简单的例子3. 性能优化方案四: 总结一: 背...
    99+
    2022-11-13
  • C++构造函数怎么使用
    这篇文章主要讲解了“C++构造函数怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++构造函数怎么使用”吧!像是结构体,我们可以使用列表初始化的方法进行初始化:struct ...
    99+
    2023-06-22
  • C++构造函数与析构函数怎么使用
    这篇文章主要讲解了“C++构造函数与析构函数怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++构造函数与析构函数怎么使用”吧!对象的初始化和清理生活中我们买的电子产品都基本会有出厂...
    99+
    2023-07-02
  • C++中拷贝构造函数的使用
    目录拷贝构造函数1. 手动定义的拷贝构造函数2. 合成的拷贝构造函数总结拷贝构造函数 拷贝构造函数,它只有一个参数,参数类型是本类的引用。复制构造函数的参数可以是 const 引用,...
    99+
    2022-11-13
  • C#中怎么使用构造函数
    本篇文章给大家分享的是有关C#中怎么使用构造函数,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。C#构造函数的名字不能随便起,必须让编译器认得出才可以被自动执行。它的命名方法既简...
    99+
    2023-06-17
  • C#中构造函数如何使用
    C#中构造函数如何使用,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。C#构造函数在使用方面及行为方面的一些特殊规则:如果开发人员没有为一个类提供构造函数,那么,...
    99+
    2023-06-17
  • C++类构造函数如何使用
    本篇文章给大家分享的是有关C++类构造函数如何使用,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。所谓C++类是定义同一类所有对象的变量和方法的蓝图或原型,C++类体内的成员是需...
    99+
    2023-06-17
  • C++构造函数怎么用
    这篇文章给大家分享的是有关C++构造函数怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1.作用一种特殊类型的方法,在每次实例化对象时运行2.代码举例2.1 示例1:#include <ios...
    99+
    2023-06-25
  • C#中如何使用结构体构造函数
    本篇文章给大家分享的是有关C#中如何使用结构体构造函数,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。///〈summary〉  ///启动服务端的参数结构&...
    99+
    2023-06-17
  • C++拷贝构造函数怎么使用
    本文小编为大家详细介绍“C++拷贝构造函数怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“C++拷贝构造函数怎么使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。构造函数只有单个形参,该形参是对本类类型对...
    99+
    2023-06-30
  • C#中的构造函数怎么用
    这篇文章主要介绍了C#中的构造函数怎么用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C#中的构造函数怎么用文章都会有所收获,下面我们一起来看看吧。C# 中的构造函数类的 构造函数 是类的一...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作