• invalid initialization of non-const reference of type与discards qualifiers


    参数传递
        
        函数参数的传递是初始化语义:用调用者的实参去初始化函数的形参,如果参数是对象,需要调用该类的拷贝构造函数,如果没有显式定义的拷贝构造函数,则执行默认的按成员拷贝
        
        返回值传递
        
        函数返回值的传递内容稍多,示例代码:
        
    1. TestClass get_test_obj()  
    2.   
    3. {  
    4.   
    5. TestClass ret_obj(200);  
    6.   
    7. return ret_obj;  
    8.   
    9. }  
    10.   
    11. void user()  
    12.   
    13. {  
    14.   
    15. TestClass obj:  
    16.   
    17. obj = get_test_obj();  
    18.   
    19. }  


        
        返回过程执行下列步骤:
        
        1、get_test_obj() 中,用返回对象 ret_obj 初始化一个类型为 TestClass(返回类型)的 临时对象 tmp_obj(假设名),这个临时对象放置在调用者 user() 的栈内。GCC 4 和 VC 2005 使用返回值临时对象的方式不同,见下面
        
        Bjarne 关于临时对象销毁的说法:临时对象在维持它的那条语句之后被销毁,除非临时对象被约束到其它名字,此时由这个命名名字控制临时对象的生存期。可以用对象初 始化的语法(显示或隐式的),或对象引用来约束这个临时对象,两者的效果是一样的,因为期间只有一个对象本体,就是临时对象的本体,约束期间不产生任何初 始化、赋值语义
        
        2、get_test_obj() 中,由 ret_obj 的生存期,决定何时将其销毁。如果 ret_obj 是局部对象(形参 或 函数内定义非 static 变量),则在返回时销毁
        
        3、如果 user() 中使用函数返回值进行 赋值操作 obj = get_test_obj(),则执行 obj.operator=(tmp_obj),没有重载的 TestClass::operator=(right) 和 ::operator=(TestClass, right) 时,执行 TestClass 的每个成员的 operator=()
        
        4、如果 user() 中使用函数返回值进行 初始化操作,包括以下几种语法:
        
        TestClass obj = get_test_obj();         // 隐式初始化
        
        TestClass obj(get_test_obj());          // 显式初始化
        
        TestClass& obj_ref = get_test_obj();    // 初始化为引用,tmp_obj 被约束到引用名
        
        隐式和显式初始化可能有 2 种实现:
        
        (1)直接将函数 get_test_obj() 返回的临时对象 tmp_obj 约束到 obj,不调用 TestClass 的任何构造函数(包括拷贝构造函数),在初始化语句执行后,不会销毁 tmp_obj,而由 obj 控制 tmp_obj 的生存期
        
        (2)调用 TestClass 的拷贝构造函数,以返回的 tmp_obj 为参数拷贝构造对象 obj.这种方式,在初始化语句执行后,tmp_obj 就没有用了,将被销毁
        
        VC 2005 采用 (1) 方式实现
        
        GCC 4 的返回值临时对象
        
        -O0 关闭编译优化
        
        无论是在 user() 内使用返回值赋值、初始化,还是不使用返回值,在 get_test_obj() 返回时,都 不创建额外的临时对象 tmp_obj,而直接将 get_test_obj() 的局部对象 TestClass ret_obj(200) 作为临时对象,即被调函数返回后,将其栈交给调用者控制,作为调用者的栈,这种返回对象的方法比 VC 2005 的效率高
        
        下面是 GCC 4 中,调用者使用函数返回值的几种情况:
        
        1、如果调用者没有使用返回值,在被调函数返回时销毁 return ret_obj 中的 ret_obj
        
        2、进行返回值赋值 或 初始化对象时,方式和 VC 2005 类似,只是不创建临时对象 tmp_obj,而使用局部对象 ret_obj
        
        3、当初始化返回值到引用名时,不能初始化到 非常量 的引用 TestClass& obj_ref = get_test_obj(),会报编译错误:
        
        error: invalid initialization of non-const reference of type 'TestClass&'
        
        from a temporary of type 'TestClass'
        
        应该使用常量引用 const TestClass& obj_ref = get_test_obj()
        
        另一个 GCC 4 有别于 VC 2005 的 const 保护行为:一个 const 对象调用的方法必需是 const 方法,比如 const TestClass obj 调用 obj.print_intval() 时,如果不是 void print_intval() const,会报编译错误:
        
        error: passing 'const TestClass' as 'this' argument of
        
        'void TestClass::print_intval()‘ discards qualifiers
  • 相关阅读:
    一个群发站内信的设计
    javascript typeof 小结
    setInterval,setTimeout的用法
    C#中常见异常类
    输入框关闭自动完成功能
    【转】javascript判断一个元素是否数组
    jquery的动态统计输入字符数方法
    giedview绑定数据格式化字符串
    jQuery 1.4单独为某个动画动作设效果
    GridView行编辑中找DropDownList控件
  • 原文地址:https://www.cnblogs.com/zhoug2020/p/4626694.html
Copyright © 2020-2023  润新知