1、move

  C++11中可以将左值强制转换为右值,从而避免对象的拷贝来提升性能。move将对象的状态或者所有权从一个对象转移到另一个对象,没有内存拷贝。深拷贝和move的区别如图:

  从图可以看出,深拷贝会有两份内存,而move只有一份,move只是将内存的所有者切换为目标对象,并没有移动任何东西,只是强制将左值转换为右值。

  在C++11之前的拷贝构造函数和赋值函数要有如下定义:

//赋值函数
T &T::operator=(const T& rhs)
{
//销毁内部资源
//复制rhs资源到自身
} //拷贝函数
A foo(); //假如foo是返回一个A类型的函数 A a;
a = foo();

  a = foo()将有如下动作:

  1. 销毁a的资源;
  2. 赋值foo返回的临时对象的资源;
  3. 销毁临时对象,释放其资源。

  其实可以优化的是,将a和临时对象的资源指针做交换,让临时对象去销毁a原来拥有的资源,a拥有临时对象的资源指针。那么赋值操作函数就该这么写:

T &T::operator=(const T& rhs)
{
//转移资源的控制权,无需复制
}

  假如一个临时容器很大,要赋值给另一个容器:

//常规
std::list<std::string> tokens; //很大容量
std::list<std::string> ret = tokens; //move
std::list<std::string> tokens; //很大容量
std::list<std::string> ret = std::move(tokens);

  如果不用move,拷贝的代价很大,性能较低,使用move几乎没有代价,只转换了资源的所有权,实际上将左值变成右值引用。move对于拥有内存、文件句柄等资源的对象有效,但是对于int、char等类型仍然会产生拷贝。当然,当一个左值被move之后,不再对之前的内存有控制权,会被置为一个空对象。

#include <iostream>

using namespace std;

int main()
{
string s = "hello";
cout << "before:" << s << endl; string s2 = move(s);
cout << "after:" << s << endl;
cout << "s2:" << s2 << endl; return ;
} //运行结果
before:hello
after:
s2:hello

2、forward完美转发

  之前的文章有提到过,当一个右值经过函数内部的转发会将其类型变成一个左值,并不是他原来的类型。

foo(int && i)
{
foo2(i);
} foo(); //5在此时是右值,在foo2调用的时候就是左值了

  那么我们该怎么优化,使参数按照原来的类型来转发呢?C++11提供了std::forward,将参数传递给函数中调用的另一个函数,按照参数本来的类型转发。

  具体用法如下:

#include <iostream>
#include <utility> using namespace std; void PrintValue(int &i)
{
cout << "Lvalue:" << i << endl;
} void PrintValue(int &&i)
{
cout << "Rvalue:" << i << endl;
} void Forward(int &&i)
{
cout << "no forward:";
PrintValue(i); //未经转发会变成左值 cout << "forward:";
PrintValue(std::forward<int>(i)); //转发
} int main()
{
int i = ; cout << "param Rvalue:" << endl;
Forward(); //cout << "param Lvalue:" << endl;
//Forward(i); //不能传入左值 cout << "move Lvalue:" << endl;
Forward(move(i)); return ;
}

C11性能之道:转移和转发的更多相关文章

  1. C11性能之道:右值引用

    1.左值与右值 C++11中新增了一种类型,右值引用,标记为T &&. 首先来介绍什么是左值和右值,左值是指表达式结束后依旧存在的持久对象,而右值是指表达式结束之后就不再存在的临时对象 ...

  2. C11性能之道:标准库优化

    1.emplace_back减少内存拷贝和移动 emplace_back能通过参数构造对象,不需要拷贝或者移动内存,相比pusk_back能更好的避免内存的拷贝和移动,使容器插入元素性能得到进一步提升 ...

  3. 品味性能之道<九>:利用Loadrunner编写socket性能测试脚本简述

            一.概述         Loadrunner拥有极为丰富的工具箱,供予我们制造出各种奇妙魔法的能力.其中就有此次要讨论的socket套接字操作.     二.socket概述     ...

  4. 品味性能之道<十一>:JAVA中switch和if性能比较

    通常而言大家普遍的认知里switch case的效率高于if else.根据我的理解而言switch的查找类似于二叉树,if则是线性查找.按照此逻辑推理对于对比条件数目大于3时switch更优,并且对 ...

  5. 品味性能之道<十>:Oracle Hint

    Hint 是Oracle 提供的一种SQL语法,它允许用户在SQL语句中插入相关的语法,从而影响SQL的执行方式. 因为Hint的特殊作用,所以对于开发人员不应该在代码中使用它,Hint 更像是Ora ...

  6. 品味性能之道<八>:Loadrunner关联技巧与字符处理

    一.概述       Loadrunner作为HP出品的性能测试工具,拥有太多奇妙魔法甜点供予性能测试人员享用,其中吃起来比较有嚼劲的那就是关联了.当然在关联之后我们还需要一些简单的字符处理,用以生成 ...

  7. 品味性能之道<七>:索引基础

    一.索引概述      索引(index),它是数据库必不可少的一部分.它其实很简单呐!很好理解.      索引好比如一本书的目录,一张地图,一个写字楼里挂在大堂墙上的公司名录,一个地铁站的出口指示 ...

  8. 品味性能之道<六>:图形化SQL分析工具

         在上一章里,重点分享了命令行SQL分析工具的使用方法.在本章将重点分享PL/SQL的SQL分析工具. 一.如何打开PL/SQL执行计划      开启PL/SQL这工具,推荐如下方法: 点击 ...

  9. 品味性能之道<五>:SQL分析工具

    一.SQL语句到底是怎么执行的? 想了解SQL语句到底是怎么执行的,那就需要进行SQL语句执行计划分析. 那什么是SQL语句执行计划呢? 就是Oracle服务器执行SQL语句的过程.例如确定是否使用索 ...

随机推荐

  1. BluetoothDevice详解

    一. BluetoothDevice简介 1. 继承关系 public static Class BluetoothDevice extends Object implement Parcelable ...

  2. ASP.NET MVC中controller和view相互传值的方式

    ASP.NET MVC中Controller向view传值的方式: ViewBag.ViewData.TempData 单个值的传递 Json 匿名类型 ExpandoObject Cookie Vi ...

  3. 3dContactPointAnnotationTool开发日志(一)

      周日毕设开题报告结束后浪了一天,今天又要开始回归正轨了.毕设要做一个人和物体的接触点标注工具,听上去好像没啥难度,其实实现起来还是挺麻烦的.   今天没做啥,就弄了个3d场景做样例.把界面搭了一下 ...

  4. python爬虫从入门到放弃(四)之 Requests库的基本使用(转)

    什么是Requests Requests是用python语言基于urllib编写的,采用的是Apache2 Licensed开源协议的HTTP库如果你看过上篇文章关于urllib库的使用,你会发现,其 ...

  5. Python的7种性能测试工具:timeit、profile、cProfile、line_profiler、memory_profiler、PyCharm图形化性能测试工具、objgraph

    1.timeit: >>> import timeit >>> def fun(): ): a = i * i >>> timeit.timeit ...

  6. MVP开发模式的理解

    1.MVP是什么 如果从层次关系来讲,MVP属于Presentation层的设计模式.对于一个UI模块来说,它的所有功能被分割为三个部分,分别通过Model.View和Presenter来承载.Mod ...

  7. SQL SERVER技术内幕之4 子查询

    最外层查询的结果集会返回给调用者,称为外部查询.内部查询的结果是供外部查询使用的,也称为子查询.子查询可以分成独立子查询和相关子查询两类.独立子查询不依赖于它所属的外部查询,而相关子查询则须依赖它所属 ...

  8. sql sever误删数据库

    在sql sever 2008 r2中,我想把一个数据库添加到DATA中,结果发现被占用,我就打算解除占用后再进行复制,本来应该先是让数据库脱离,再复制,结果,我自作聪明地右键数据库,选择了删除,结果 ...

  9. [剑指Offer] 59.按之字形顺序打印二叉树

    题目描述 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推. [思路]先按层次遍历存入,通过设立标志位,将 ...

  10. 【数据库】Sql Server 2008完全卸载方法(其他版本类似)

    本文介绍如何卸载 Microsoft SQL Server 2008的方法.当您按照本文中的步骤时,您还准备系统以便可以重新安装 SQL Server 2008版本 一.    SQL2008卸载. ...