背景及问题

如下程序所示:

#include<iostream>

class MyString {
public:
MyString() = default;
MyString(const char* data)
{
printf("%s", "MyString Constructed!!\n");
size = strlen(data);
m_data = new char[size];
memcpy(m_data, data, size);
}
~MyString()
{
if (m_data)
{
printf("%s", "MyString Destroyed!!\n");
delete m_data;
}
}
//copy constructor
MyString(const MyString& other) noexcept
{
printf("%s", "MyString Copyed!!\n");
size = other.size;
m_data = new char[size];
memcpy(m_data, other.m_data, size);
} private:
char* m_data;
int size;
}; class Entity
{
public:
//constructor
Entity(const MyString& string):m_string(string) {}
private:
MyString m_string;
}; int main()
{ Entity entity("Hello");
return 0;
}

程序说明

程序定义了一个MyString类,其中构造函数和拷贝构造函数需要对传进来的字符串开辟空间并复制内容,另外一个Entity类含有一个MyString成员,并在初始化时复制传入的MyString对象。主程序Main中以常量字符串构造一个entity示例。

运行程序会发现,MyString构造了一次,拷贝一次,程序结束析构两次,符合运行逻辑。“Hello”字符串先通过构造函数构造一个临时变量MyString,临时变量再通过Entity内的构造函数拷贝构造给成员变量m_string

问题在于临时变量拷贝构造需要重新开辟空间,并且“用完即扔”,为什么不直接将“hello”构造好的MyString直接“移动”到Entity?这样会节省空间,提高效率。用此引出移动构造和std::move()

移动构造与std::move()

若要实现将临时变量移动到Entity,首先MyString要加入移动构造,如下:

	MyString(MyString&& other) noexcept
{
printf("%s", "MyString Moved!!\n");
size = other.size;
m_data = other.m_data; //clear origin data
other.size = 0;
other.m_data = nullptr;
}

此为移动构造,接受的是一个右值,构造是直接复制原MyString的size与data,不重新开辟空间做深拷贝。并将原MyString清零。接着对Entity构造时使用std::move通知移动构造函数,如下:

	Entity(MyString&& string) :m_string(std::move(string)) {}

需要注意的是

1. Entity右值构造时也可不使用std::move,直接将参数强转为右值类型也可以,std::move相当于通知构造函数以移动构造的方式进行

Entity(MyString&& string) :m_string((MyString&&)string) {}

2. 对于形参为Const YourType &类型的既可以接受左值,也可以接受右值。但是使用std::move会编译错误,因为Const值不能被移动,所以Entity构造仍要单独写一个右值构造

3. MyString移动构造时,复制了临时数据的值还要对其清空,因为数据已经被移动,指针没有置空,析构两次会引起Crash问题

C++移动构造与std::move()的更多相关文章

  1. 移动构造和移动赋值与std::move

    ------------------------------------移动构造------------------------------------------ 传统的深拷贝深赋值 对于类中,含有 ...

  2. C++ 11 右值引用以及std::move

    转载请注明出处:http://blog.csdn.net/luotuo44/article/details/46779063 新类型: int和int&是什么?都是类型.int是整数类型,in ...

  3. C++11右值引用和std::move语句实例解析

    关键字:C++11,右值引用,rvalue,std::move,VS 2015 OS:Windows 10 右值引用(及其支持的Move语意和完美转发)是C++0x将要加入的最重大语言特性之一.从实践 ...

  4. c++ 11 移动语义、std::move 左值、右值、将亡值、纯右值、右值引用

    为什么要用移动语义 先看看下面的代码 // rvalue_reference.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #includ ...

  5. C++ 11 左值,右值,左值引用,右值引用,std::move, std::foward

    这篇文章要介绍的内容和标题一致,关于C++ 11中的这几个特性网上介绍的文章很多,看了一些之后想把几个比较关键的点总结记录一下,文章比较长.给出了很多代码示例,都是编译运行测试过的,希望能用这些帮助理 ...

  6. item 23: 理解std::move和std::forward

    本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 根据std::move和std::forward不 ...

  7. Item 25: 对右值引用使用std::move,对universal引用则使用std::forward

    本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 右值引用只能绑定那些有资格被move的对象上去.如 ...

  8. [转载]如何在C++03中模拟C++11的右值引用std::move特性

    本文摘自: http://adamcavendish.is-programmer.com/posts/38190.htm 引言 众所周知,C++11 的新特性中有一个非常重要的特性,那就是 rvalu ...

  9. std::move的原理与实现,右值引用的深入理解

    这次我真的懂了.... 首先C++11引入了右值引用 && ‘&&’这个要连起来看,是一个整体,C++多了一个关键字而已. 不是引用的引用.是船新的一种语法.那有什么用 ...

  10. 透彻理解C++11新特性:右值引用、std::move、std::forward

    目录 浅拷贝.深拷贝 左值.右值 右值引用类型 强转右值 std::move 重新审视右值引用 右值引用类型和右值的关系 函数参数传递 函数返还值传递 万能引用 引用折叠 完美转发 std::forw ...

随机推荐

  1. php+bootstrap+jquery+mysql实现购物车项目案例

    获取源码 一键三连后,评论区留下邮箱安排发送:) 介绍 使用php,bootstrap,jquery,mysql实现的简易购物车案例. 通过本案例,你将学习到以下知识点: php 操作 mysql 实 ...

  2. [Android 逆向]Xposed 破解 切水果大战原版.apk

    代码 public class Main implements IXposedHookLoadPackage { boolean flag = false; @Override public void ...

  3. CSS font-weight

    主要理解UI给得英文名 对应得数值 字体粗细:'font-weight'属性名称: font-weight取值: normal | bold | bolder | lighter | 100 | 20 ...

  4. go词法作用域陷进

    问题 // 创建一些目录,再将目录删除 // 错误写法 var rmdirs []func() for _, dir := range tempDirs() { os.MkdirAll(dir, 07 ...

  5. VMware虚拟机Ubuntu系统连接网络过程

    网络和Internet设置--高级网络设置--更多网络适配器选项--WLAN. 右键选择属性--共享,勾选允许连接,选择VMnet8.(若勾选了其它,之后再想换回来,可以先取消勾选,点确定,再进入勾选 ...

  6. 教程|在矩池云使用 Stable Diffusion web UI v1.5 模型和 ControlNet 插件

    今天给大家介绍下如何在矩池云使用 Stable Diffusion web UI v1.5 模型和 Stable Diffusion ControlNet 插件. 租用机器 租用机器需要选择内存大于8 ...

  7. jvm调优监控工具jps、jstack、jmap、jhat、jstat使用详解

    目录 前言 jps(Java Virtual Machine Process Status Tool) jstack jmap(Memory Map)和jhat(Java Heap Analysis ...

  8. C#的Winform程序关于单击和双击的区别 - 开源研究系列文章

    前些天编码的时候有个关于应用程序的托盘图标的鼠标Mouse Down里的单击和双击的问题,只是想单击的时候显示主窗体,双击的时候显示操作窗体.但是编码并调试的时候发现Windows的鼠标双击的事件先执 ...

  9. 【2024面试刷题】一、Spring Cloud 面试题

    1.什么是 Spring Cloud? Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如 服务发现注册.配置中心.智能路 ...

  10. 在anaconda中为jupyter安装代码自动补全或代码自动提示功能,jupyter nbextensions不显示拓展,另附格式化代码插件的安装方法

    操作步骤 进入命令行环境.我使用的是conda.有两种方式进入命令行. 方法1:通过anconda navigator界面,选择environments,选择对应环境名,选择open terminal ...