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. Linux 应用笔记

    Linux 应用笔记 Linux 应用笔记 小书匠 Raspberry Pi 常用命令 CentOs Raspberry Ubuntu python 实用教程 Vim 权限问题 内存分配 shell ...

  2. “hello world!”团队第三次会议

    团队“hello world!”团队召开的第三次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 一.会议时间 2017年10 ...

  3. 《剑指offer》---输出链表倒数第k个结点

    本文算法使用python3实现 1 题目描述:   输入一个链表,输出该链表中倒数第k个结点.   时间限制:1s:空间限制:32768K 2 思路描述:   方法一:当链表长度为 $ n $ 时,输 ...

  4. iOS- 网络请求的两种常用方式【GET & POST】的区别

    GET和POST 网络请求的两种常用方式的实现[GET & POST] –GET的语义是获取指定URL上的资源 –将数据按照variable=value的形式,添加到action所指向的URL ...

  5. 数字证书认证这点事, SSL/TLS,OpenSSL

    1.概念 数字证书 HTTPS请求时,Server发给浏览器的认证数据,用私钥签名,并且告诉浏览器公钥,利用公钥解密签名,确认Server身份. 证书还会指明相应的CA,CA能确认证书是否真的是CA颁 ...

  6. Android基础------高级ul:消息提示

    前言:Android消息提示笔记,刚刚接触Android 1.静态方法Toast 直接调用静态方法 //消息提示(context,"内容",固定时间) Toast.makeText ...

  7. [OS] 操作系统-进程线程-经典面试笔试题

    题目转自:http://blog.csdn.net/morewindows/article/details/7392749 ·线程的基本概念.线程的基本状态及状态之间的关系? 线程,有时称为轻量级进程 ...

  8. 第69天:jQuery入口函数

    一.jQuery入口函数 1.$(document).ready(function(){}); 2.$(function(){}); 二.事件处理程序  1.事件源 Js方式:document.get ...

  9. 【python】python sqlalchemy core

    SQLAlchemy是和很多数据库进行交互的一个库,他可以让你创建model,让你可以以一种Python中面向对象的方式进行查询.使得你的代码和数据库可以分开,也就是减轻他们之间的依赖.让你进行数据库 ...

  10. Android命名格式化详解

     严格换行 一般情况下一个“:”一换行 建议函数的“{}”分别占一行 例:public void ooSomething() { …… } 不要用: 例:public void doSomething ...