• 模板与c++11--右值引用


    函数参数传递

     1 struct huge_data{
     2     char *content;
     3     unsigned sz;
     4     huge_data():content(0),sz(0){
     5         cout<<this<<"->huge_data()"<<endl;
     6     }
     7 
     8     huge_data(unsigned sz):content(new char[sz]),sz(sz){
     9         cout<<this<<"->huge_data("<<sz<<")"<<endl;
    10     }
    11 
    12     huge_data(huge_data const &h):content(new char[h.sz]),sz(h.sz){
    13         copy(h.content,h.content+sz,content);
    14         cout<<this<<"->huge_data("<<&h<<")"<<endl;
    15     }
    16 
    17     huge_data &operator=(huge_data const &h){
    18         if(&h == this) return *this;
    19         if(content) delete[] content;
    20 
    21         content = new char[h.sz];
    22         copy(h.content,h.content+sz,content);
    23         sz = h.sz;
    24         cout<<this<<"->operator=("<<&h<<")"<<endl;
    25         return *this;
    26     }
    27     ~huge_data(){
    28         if(content){
    29             delete[] content;
    30         }
    31     }
    32 };
    33 
    34 huge_data prepare_data(unsigned sz){
    35     huge_data h(sz);
    36     memset(h.content,'a',sizeof(char)*sz);
    37     return h;
    38 }
    39 
    40 class BFS{
    41 public:
    42     void test(){
    43         cout<<"begin"<<endl;
    44         huge_data a;
    45         a = prepare_data(1024);
    46 
    47 
    48         cout<<"end"<<endl;
    49     }
    50 };

    参数传递的详细步骤:

    1,在test函数的call back上预留能保存huge_data实例的空间,并将其地址作为prepare_data的参数传递到调用栈

    2,prepare_data调用huge_data的构造函数为其局部变量h创建huge_data的实例,在函数返回时将h的内容copy构造到test函数的预留空间中

    3,test函数再调用赋值操作符=从值从预留空间赋值到a上并释放预留空间

    在编译取消优化选项g++ -fno-elide-constructors test.cpp

    begin
    0x7ffecce0c7f0->huge_data()
    0x7ffecce0c7b0->huge_data(1024)
    0x7ffecce0c800->huge_data(0x7ffecce0c7b0)
    0x7ffecce0c7f0->operator=(0x7ffecce0c800)
    end
    
    Process returned 0 (0x0)   execution time : 0.003 s
    Press ENTER to continue.

    如果使用编译优化选项的话,就是编译时去掉-fno-elide-constructors

    begin
    0x7ffd15fa0db0->huge_data()
    0x7ffd15fa0dc0->huge_data(1024)
    0x7ffd15fa0db0->operator=(0x7ffd15fa0dc0)
    end

    可以看到省略了一次copy构造函数的调用,

    -fno-elide-constructors
    The C++ standard allows an implementation to omit creating a temporary which is only used to initialize another object of the same type. Specifying this option disables that optimization, and forces G++ to call the copy constructor in all cases.

    g++ 编译选项,no-elide-constructors,标准c++允许这样的机制,当被用来初始化另一个相同类型的另外对象时,省略产生临时变量。如果 指定了-fno-elide-constructors选项,可以禁止此项优化,强制使g++在所有的cases中调用copy constructor。

    =========================================

    左值,非左值

    在c语言中可用于区分赋值和不可赋值的对象。左值可放在复制语句、等号左边的对象,也就是可以进行赋值的对象。常见的左值包括任何变量、指针去引用表达式,而典型的非左值由常数和函数调用。

    int *pass(int *p) {return p;}

    void main(){

      int a,*p;

      a = 1;

      p = &a;//指针取引用表达式也是左值

      1 = 2;//常量1不能进行复制,非左值

      pass(p) = &a;//函数返回值也不是左值

      *pass(p) = 1;//但是指针去引用后,还是左值

    }

    c++中左值的本质含义: B.Kernighan与D.Ritchie给出的,所谓对象是agiel具有名称的存储空间,1左值则是意味着某个对象的表达式。

    就是说,如果表达式意指一个具名的存储空间,也就意味着随后这一存储空间中的内容还可以依据其名字而获取,则当前对该存储空间的值进行修改(如赋值),才可行。

    非左值,1根本没有存储空间的数值,如各种常数,可能在编译时直接优化成指令中的常数而没有存储空间,显然其内容也无法修改。

        2指某个无名存储空间的表达式(右值)。

    =============

    右值,指某个无名存储空间的表达式,如果某个存储空间无名,意味着现在修改了其中的内容,也无法找到该空间再提取其内容,以前的c++标准是禁止修改右值中的内容。

    但是在c++11引入右值引用后,是可以的。

    某一类型的右值引用类型写为T&&,原有引用类型T&表示左值引用。

    ====什么情况可以使用右值引用?

    右值引用赋予了我们更改右值内容的权利,如左值引用类型一样,右值引用类型可用于函数参数,也可以声明局部变量。

    =====移动构造与移动复制

  • 相关阅读:
    纪念一下Jerry
    在中信66楼微软Offic参加讲座
    关于地理信息信息点数据采集一些方法
    简单的C#进行图片操作
    PHP访问C#建立的Webservice
    搜索引擎一:介绍
    介绍一况挺好用的Javascript编辑器(带项目)
    服务器不支持WebResource.axd的特殊处理
    Daily Web Words
    php psr 编码规范(PSR[04])
  • 原文地址:https://www.cnblogs.com/li-daphne/p/5545638.html
Copyright © 2020-2023  润新知