C11性能之道:转移和转发

1、move

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

C11性能之道:转移和转发

  从图可以看出,深拷贝会有两份内存,而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 0;
}

//运行结果
before:hello
after:
s2:hello

2、forward完美转发

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

foo(int && i)
{
    foo2(i);
}

foo(5);  //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 = 1;

    cout << "param Rvalue:" << endl;
    Forward(2);

    //cout << "param Lvalue:" << endl;
    //Forward(i);              //不能传入左值
    
    cout << "move Lvalue:" << endl;
    Forward(move(i));

    return 0;
}

原文链接: https://www.cnblogs.com/ChinaHook/p/7684204.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C11性能之道:转移和转发

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/399412

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月13日 上午9:22
下一篇 2023年4月13日 上午9:22

相关推荐