• C++临时对象的生命期


    class Test{
    public:
        Test(int a):m_int(a){
            printf("this is Test(%d) ctor
    ", m_int);
        }
        ~Test(){
            printf("this is Test(%d) dtor
    ", m_int);
        }
        const Test & testfun() const{
            printf("this is %d testfun
    ", m_int);
            return *this;
        }
    private:
        int m_int;
    };
    
    struct S {
        int mi;
    const Test& mt;
        ~S(){
            printf("this is S dtor
    ");
        }
    };

     Whenever a reference is bound to a temporary or to a subobject thereof, the lifetime of the temporary is extended to match the lifetime of the reference, with the following exceptions:

             当临时对象绑定到引用上时,临时对象的生命期也会跟随引用的生命期而得到延长,但是也有一些特殊情况:

    a temporary bound to a return value of a function in a return statement is not extended: it is destroyed immediately at the end of the return expression. Such function always returns a dangling reference.

             对于返回引用的函数,如果函数中的return语句返回的是一个临时对象,则该临时对象在return语句的最后就会被销毁。这种情况下,该函数返回的引用实际上就是个“空悬引用”(dangling reference)。实际上即使不是临时对象,只要是返回函数内部对象的引用,在return之后,该引用就是空悬引用了:

    const Test & fun(){
        return Test(3);
    }
    
    int main(int argc, char **argv){
        const Test &aa = fun();
        printf("over
    ");
        aa.testfun();
    }

              上面的代码,在编译时就会报警:warning: returning reference to temporary [-Wreturn-local-addr]  return Test(3);

             代码结果如下:

    this is Test(3) ctor
    this is Test(3) dtor
    over
    Segmentation fault (core dumped)

              实际上,最后的段错误有可能发生,也有可能不发生,重要的是,const Test &aa = fun();之后,aa已经是个空悬引用了。

    a temporary bound to a reference member in a constructor initializer list persists only until the constructor exits, not as long as the object exists. (note: such initialization is ill-formed as of DR 1696).  (until C++14)

             在initializer list形式的构造函数中,如果临时对象绑定到一个对象A的引用成员中,则该临时对象的生命期在构造函数结束后就会结束,并不跟随对象A的生命期而得到延长。但是这一条规则在C++14之后就不再使用了。下面的代码验证了这一点:

        S ss {1, Test(1) }; 
        printf("over
    ");
        ss.mt.testfun();

              代码的结果如下:

    this is Test(1) ctor
    over
    this is 1 testfun
    this is Test(1) dtor
    this is S dtor

              可见,S中的引用成员mt绑定到了一个临时对象,该临时对象的生命期跟随ss而得到了延长。

    a temporary bound to a reference parameter in a function call exists until the end of the full expression containing that function call: if the function returns a reference, which outlives the full expression, it becomes a dangling reference.

             如果函数参数为引用,当临时对象绑定到该参数上时,其生命期一直持续到包含该函数调用的表达式的结束,如果该函数又返回了该引用,则该引用成为空悬引用:

    const Test & fun3(const Test &a){
        a.testfun();
        return a;
    }
    
    int main(int argc, char **argv){
        const Test &a = fun3(Test(2)).testfun(); 
        printf("over
    ");
        a.testfun();
    }

              代价结果如下:

    this is Test(2) ctor
    this is 2 testfun
    this is 2 testfun
    this is Test(2) dtor
    over
    this is 2 testfun

              尽管最后的testfun打印出了结果,但是这是未定义行为。

    a temporary bound to a reference in the initializer used in a new-expression exists until the end of the full expression containing that new-expression, not as long as the initialized object. If the initialized object outlives the full expression, its reference member becomes a dangling reference.

             如果临时对象绑定到了一个在new表达式中初始化的引用,则该临时对象的生命期一直持续到包含new的表达式的结束,而不是跟随new出来的对象的生命期而得到延长,此时,该对象中的引用成员在表达式结束之后,就成了空悬引用:

        S *p = new S{1, Test(3) };
        printf("p->mi is %d
    ", p->mi);
        p->mt.testfun();

              代码结果如下:

    this is Test(3) ctor
    this is Test(3) dtor
    over
    p->mi is 1
    this is 3 testfun

              尽管最后的testfun打印出了结果,但是这是未定义行为。

    In general, the lifetime of a temporary cannot be further extended by "passing it on": a second reference, initialized from the reference to which the temporary was bound, does not affect its lifetime.

             一般而言,临时对象的生命期并不能随着引用的传递而得到延长:如果临时对象绑定到了引用A,而使用引用A又初始化了引用B,这种情况下,引用B对临时对象的生命周期没有影响。

    https://en.cppreference.com/w/cpp/language/reference_initialization

  • 相关阅读:
    第01组 团队Git现场编程实战
    2019 SDN上机第1次作业
    第二次结对编程作业
    团队项目-需求分析报告
    团队项目-选题报告
    2019 SDN阅读作业
    2019 SDN上机第3次作业
    2019 SDN上机第2次作业
    2019 SDN上机第1次作业
    OpenDayLight安装Features
  • 原文地址:https://www.cnblogs.com/gqtcgq/p/9678740.html
Copyright © 2020-2023  润新知